diff --git a/Makefile b/Makefile index 67b5ac35..6891e155 100644 --- a/Makefile +++ b/Makefile @@ -12,14 +12,13 @@ EXTRA_FLAGS := $(PYTHON_INCLUDE) LDFLAGS += $(shell if $(PYTHON_CONFIG) --ldflags --embed >/dev/null; then $(PYTHON_CONFIG) --ldflags --embed; else $(PYTHON_CONFIG) --ldflags; fi) # Either finds numpy or set -DWITHOUT_NUMPY -EXTRA_FLAGS += $(shell $(PYTHON_BIN) $(CURDIR)/numpy_flags.py) -WITHOUT_NUMPY := $(findstring $(EXTRA_FLAGS), WITHOUT_NUMPY) +CXXFLAGS += $(shell $(PYTHON_BIN) $(CURDIR)/numpy_flags.py) +WITHOUT_NUMPY := $(findstring $(CXXFLAGS), WITHOUT_NUMPY) # Examples requiring numpy support to compile EXAMPLES_NUMPY := surface colorbar -EXAMPLES := minimal basic modern animation nonblock xkcd quiver bar \ - fill_inbetween fill update subplot2grid lines3d \ - $(if $(WITHOUT_NUMPY),,$(EXAMPLES_NUMPY)) +EXAMPLES := minimal basic modern eventplot animation nonblock xkcd quiver bar fill_inbetween fill update subplot2grid lines3d\ + $(if WITHOUT_NUMPY,,$(EXAMPLES_NUMPY)) # Prefix every example with 'examples/build/' EXAMPLE_TARGETS := $(patsubst %,examples/build/%,$(EXAMPLES)) diff --git a/examples/eventplot.cpp b/examples/eventplot.cpp new file mode 100644 index 00000000..417650f2 --- /dev/null +++ b/examples/eventplot.cpp @@ -0,0 +1,36 @@ +#define _USE_MATH_DEFINES +#include +#include +#include "../matplotlibcpp.h" + +namespace plt = matplotlibcpp; + +int main() +{ + // Prepare data. + std::vector> events; + events.push_back({2,5,10,25}); + events.push_back({20,21,22,24}); + events.push_back({4,8,12,14,16,17,18}); + events.push_back({10,11,12,13.5}); + + + + // Set the size of output image = 1200x780 pixels + plt::figure_size(1200, 780); + std::map keywords; + keywords["linewidths"] = "0.5"; + keywords["colors"] = "black"; + plt::eventplot(events, keywords); + + // Add graph title + plt::title("Event plot"); + plt::xlabel("Time in ms"); + plt::ylabel("Neuron ID"); + + plt::show(); + // save figure + const char* filename = "./events.png"; + std::cout << "Saving result to " << filename << std::endl;; + plt::save(filename); +} diff --git a/examples/fill_inbetween.cpp b/examples/fill_inbetween.cpp index 788d0086..a388c1c7 100644 --- a/examples/fill_inbetween.cpp +++ b/examples/fill_inbetween.cpp @@ -19,7 +19,7 @@ int main() { // Prepare keywords to pass to PolyCollection. See // https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.fill_between.html std::map keywords; - keywords["alpha"] = "0.4"; + //keywords["alpha"] = 0.4; keywords["color"] = "grey"; keywords["hatch"] = "-"; diff --git a/matplotlibcpp.h b/matplotlibcpp.h index 67700740..b397a2b5 100644 --- a/matplotlibcpp.h +++ b/matplotlibcpp.h @@ -54,6 +54,7 @@ struct _interpreter { PyObject *s_python_function_figure; PyObject *s_python_function_fignum_exists; PyObject *s_python_function_plot; + PyObject *s_python_function_eventplot; PyObject *s_python_function_quiver; PyObject* s_python_function_contour; PyObject *s_python_function_semilogx; @@ -108,6 +109,9 @@ struct _interpreter { static _interpreter& get() { static _interpreter ctx; +#ifndef WITHOUT_NUMPY + ctx.import_numpy(); +#endif return ctx; } @@ -180,7 +184,9 @@ struct _interpreter { PyObject* pymod = PyImport_Import(pyplotname); Py_DECREF(pyplotname); - if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); } + if (!pymod) { + throw std::runtime_error("Error loading module matplotlib.pyplot!"); + } s_python_colormap = PyImport_Import(cmname); Py_DECREF(cmname); @@ -188,7 +194,9 @@ struct _interpreter { PyObject* pylabmod = PyImport_Import(pylabname); Py_DECREF(pylabname); - if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); } + if (!pylabmod) { + throw std::runtime_error("Error loading module pylab!"); + } s_python_function_arrow = safe_import(pymod, "arrow"); s_python_function_show = safe_import(pymod, "show"); @@ -239,7 +247,8 @@ struct _interpreter { s_python_function_suptitle = safe_import(pymod, "suptitle"); s_python_function_bar = safe_import(pymod,"bar"); s_python_function_colorbar = PyObject_GetAttrString(pymod, "colorbar"); - s_python_function_subplots_adjust = safe_import(pymod,"subplots_adjust"); + s_python_function_subplots_adjust = safe_import(pymod,"subplots_adjust"); + s_python_function_eventplot = PyObject_GetAttrString(pymod, "eventplot"); #ifndef WITHOUT_NUMPY s_python_function_imshow = safe_import(pymod, "imshow"); #endif @@ -247,7 +256,7 @@ struct _interpreter { } ~_interpreter() { - Py_Finalize(); + //Py_Finalize(); } }; @@ -270,7 +279,6 @@ inline void backend(const std::string& name) inline bool annotate(std::string annotation, double x, double y) { detail::_interpreter::get(); - PyObject * xy = PyTuple_New(2); PyObject * str = PyString_FromString(annotation.c_str()); @@ -297,30 +305,55 @@ namespace detail { #ifndef WITHOUT_NUMPY // Type selector for numpy array conversion -template struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default -template <> struct select_npy_type { const static NPY_TYPES type = NPY_DOUBLE; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_FLOAT; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_BOOL; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT8; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_SHORT; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT64; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_UINT8; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_USHORT; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_ULONG; }; -template <> struct select_npy_type { const static NPY_TYPES type = NPY_UINT64; }; +template struct select_npy_type { + const static NPY_TYPES type = NPY_NOTYPE; +}; //Default +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_DOUBLE; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_FLOAT; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_BOOL; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_INT8; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_SHORT; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_INT; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_INT64; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_UINT8; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_USHORT; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_ULONG; +}; +template <> struct select_npy_type { + const static NPY_TYPES type = NPY_UINT64; +}; // Sanity checks; comment them out or change the numpy type below if you're compiling on // a platform where they don't apply -static_assert(sizeof(long long) == 8); +static_assert(sizeof(long long) == 8, "Sanity check, see source code!"); template <> struct select_npy_type { const static NPY_TYPES type = NPY_INT64; }; -static_assert(sizeof(unsigned long long) == 8); +static_assert(sizeof(unsigned long long) == 8, "Sanity check, see source code!"); template <> struct select_npy_type { const static NPY_TYPES type = NPY_UINT64; }; // TODO: add int, long, etc. template PyObject* get_array(const std::vector& v) { + detail::_interpreter::get(); npy_intp vsize = v.size(); NPY_TYPES type = select_npy_type::type; if (type == NPY_NOTYPE) { @@ -342,7 +375,7 @@ template PyObject* get_2darray(const std::vector<::std::vector>& v) { if (v.size() < 1) throw std::runtime_error("get_2d_array v too small"); - + detail::_interpreter::get(); npy_intp vsize[2] = {static_cast(v.size()), static_cast(v[0].size())}; @@ -366,6 +399,7 @@ PyObject* get_2darray(const std::vector<::std::vector>& v) template PyObject* get_array(const std::vector& v) { + detail::_interpreter::get(); PyObject* list = PyList_New(v.size()); for(size_t i = 0; i < v.size(); ++i) { PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i))); @@ -378,6 +412,7 @@ PyObject* get_array(const std::vector& v) // sometimes, for labels and such, we need string arrays inline PyObject * get_array(const std::vector& strings) { + detail::_interpreter::get(); PyObject* list = PyList_New(strings.size()); for (std::size_t i = 0; i < strings.size(); ++i) { PyList_SetItem(list, i, PyString_FromString(strings[i].c_str())); @@ -389,6 +424,7 @@ inline PyObject * get_array(const std::vector& strings) template PyObject* get_listlist(const std::vector>& ll) { + detail::_interpreter::get(); PyObject* listlist = PyList_New(ll.size()); for (std::size_t i = 0; i < ll.size(); ++i) { PyList_SetItem(listlist, i, get_array(ll[i])); @@ -404,6 +440,7 @@ PyObject* get_listlist(const std::vector>& ll) template bool plot(const std::vector &x, const std::vector &y, const std::map& keywords) { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -443,8 +480,8 @@ void plot_surface(const std::vector<::std::vector> &x, const std::map &keywords = std::map()) { - detail::_interpreter::get(); - + detail::_interpreter::get(); + // We lazily load the modules here the first time this function is called // because I'm not sure that we can assume "matplotlib installed" implies // "mpl_toolkits installed" on all platforms, and we don't want to require @@ -616,9 +653,64 @@ void plot3(const std::vector &x, if (res) Py_DECREF(res); } +template +bool eventplot(const std::vector> &events, const std::map& keywords = std::map()) +{ + detail::_interpreter::get(); + PyObject *list = PyList_New(events.size()); + // using numpy arrays + for (size_t i = 0; i < events.size(); i++) { + PyList_SetItem(list, i, detail::get_array(events[i])); + } + + PyObject *res; + // construct positional args + PyObject *args = PyTuple_New(1); + PyTuple_SetItem(args, 0, list); + + if (keywords.size() > 0) { + // construct keyword args + PyObject *kwargs = PyDict_New(); + for (std::map::const_iterator it = + keywords.begin(); + it != keywords.end(); ++it) { + bool is_number = false; + double value = 0.0; + try { + value = std::stod(it->second.c_str()); + is_number = true; + } + catch( ... ) {} + if(is_number) { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyFloat_FromDouble(value)); + } + else { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyString_FromString(it->second.c_str())); + } + } + + res = PyObject_Call( + detail::_interpreter::get().s_python_function_eventplot, args, + kwargs); + Py_DECREF(kwargs); + } + else { + res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_eventplot, args); + } + + Py_DECREF(args); + if (res) + Py_DECREF(res); + return res; +} + template bool stem(const std::vector &x, const std::vector &y, const std::map& keywords) { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -635,13 +727,13 @@ bool stem(const std::vector &x, const std::vector &y, const st // construct keyword args PyObject* kwargs = PyDict_New(); for (std::map::const_iterator it = - keywords.begin(); it != keywords.end(); ++it) { + keywords.begin(); it != keywords.end(); ++it) { PyDict_SetItemString(kwargs, it->first.c_str(), - PyString_FromString(it->second.c_str())); + PyString_FromString(it->second.c_str())); } PyObject* res = PyObject_Call( - detail::_interpreter::get().s_python_function_stem, args, kwargs); + detail::_interpreter::get().s_python_function_stem, args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -654,6 +746,7 @@ bool stem(const std::vector &x, const std::vector &y, const st template< typename Numeric > bool fill(const std::vector& x, const std::vector& y, const std::map& keywords) { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -686,10 +779,10 @@ bool fill(const std::vector& x, const std::vector& y, const st template< typename Numeric > bool fill_between(const std::vector& x, const std::vector& y1, const std::vector& y2, const std::map& keywords) { + detail::_interpreter::get(); assert(x.size() == y1.size()); assert(x.size() == y2.size()); - detail::_interpreter::get(); // using numpy arrays PyObject* xarray = detail::get_array(x); @@ -753,7 +846,6 @@ bool hist(const std::vector& y, long bins=10,std::string color="b", double alpha=1.0, bool cumulative=false) { detail::_interpreter::get(); - PyObject* yarray = detail::get_array(y); PyObject* kwargs = PyDict_New(); @@ -861,7 +953,6 @@ bool scatter(const std::vector& x, const std::map & keywords = {}) { detail::_interpreter::get(); - assert(x.size() == y.size()); PyObject* xarray = detail::get_array(x); @@ -993,8 +1084,8 @@ bool bar(const std::vector & y, std::string ec = "black", std::string ls = "-", double lw = 1.0, - const std::map & keywords = {}) -{ + const std::map & keywords = {}) { + detail::_interpreter::get(); using T = typename std::remove_reference::type::value_type; detail::_interpreter::get(); @@ -1008,7 +1099,6 @@ bool bar(const std::vector & y, inline bool subplots_adjust(const std::map& keywords = {}) { detail::_interpreter::get(); - PyObject* kwargs = PyDict_New(); for (std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) { @@ -1032,8 +1122,7 @@ template< typename Numeric> bool named_hist(std::string label,const std::vector& y, long bins=10, std::string color="b", double alpha=1.0) { detail::_interpreter::get(); - - PyObject* yarray = detail::get_array(y); + PyObject* yarray = get_array(y); PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(label.c_str())); @@ -1057,6 +1146,7 @@ bool named_hist(std::string label,const std::vector& y, long bins=10, s template bool plot(const std::vector& x, const std::vector& y, const std::string& s = "") { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -1070,7 +1160,6 @@ bool plot(const std::vector& x, const std::vector& y, const PyTuple_SetItem(plot_args, 0, xarray); PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); Py_DECREF(plot_args); @@ -1115,6 +1204,7 @@ bool contour(const std::vector& x, const std::vector& y, template bool quiver(const std::vector& x, const std::vector& y, const std::vector& u, const std::vector& w, const std::map& keywords = {}) { + detail::_interpreter::get(); assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size()); detail::_interpreter::get(); @@ -1151,6 +1241,7 @@ bool quiver(const std::vector& x, const std::vector& y, cons template bool stem(const std::vector& x, const std::vector& y, const std::string& s = "") { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -1166,7 +1257,7 @@ bool stem(const std::vector& x, const std::vector& y, const PyTuple_SetItem(plot_args, 2, pystring); PyObject* res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_stem, plot_args); + detail::_interpreter::get().s_python_function_stem, plot_args); Py_DECREF(plot_args); if (res) @@ -1178,6 +1269,7 @@ bool stem(const std::vector& x, const std::vector& y, const template bool semilogx(const std::vector& x, const std::vector& y, const std::string& s = "") { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -1203,6 +1295,7 @@ bool semilogx(const std::vector& x, const std::vector& y, co template bool semilogy(const std::vector& x, const std::vector& y, const std::string& s = "") { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -1228,6 +1321,7 @@ bool semilogy(const std::vector& x, const std::vector& y, co template bool loglog(const std::vector& x, const std::vector& y, const std::string& s = "") { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -1253,6 +1347,7 @@ bool loglog(const std::vector& x, const std::vector& y, cons template bool errorbar(const std::vector &x, const std::vector &y, const std::vector &yerr, const std::map &keywords = {}) { + detail::_interpreter::get(); assert(x.size() == y.size()); detail::_interpreter::get(); @@ -1291,7 +1386,6 @@ template bool named_plot(const std::string& name, const std::vector& y, const std::string& format = "") { detail::_interpreter::get(); - PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); @@ -1317,7 +1411,6 @@ template bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") { detail::_interpreter::get(); - PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); @@ -1344,7 +1437,6 @@ template bool named_semilogx(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") { detail::_interpreter::get(); - PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); @@ -1371,7 +1463,6 @@ template bool named_semilogy(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") { detail::_interpreter::get(); - PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); @@ -1398,7 +1489,6 @@ template bool named_loglog(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") { detail::_interpreter::get(); - PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); @@ -1448,7 +1538,6 @@ template void text(Numeric x, Numeric y, const std::string& s = "") { detail::_interpreter::get(); - PyObject* args = PyTuple_New(3); PyTuple_SetItem(args, 0, PyFloat_FromDouble(x)); PyTuple_SetItem(args, 1, PyFloat_FromDouble(y)); @@ -1489,7 +1578,6 @@ inline void colorbar(PyObject* mappable = NULL, const std::map void ylim(Numeric left, Numeric right) { detail::_interpreter::get(); - PyObject* list = PyList_New(2); PyList_SetItem(list, 0, PyFloat_FromDouble(left)); PyList_SetItem(list, 1, PyFloat_FromDouble(right)); @@ -1606,7 +1693,6 @@ template void xlim(Numeric left, Numeric right) { detail::_interpreter::get(); - PyObject* list = PyList_New(2); PyList_SetItem(list, 0, PyFloat_FromDouble(left)); PyList_SetItem(list, 1, PyFloat_FromDouble(right)); @@ -1625,7 +1711,6 @@ void xlim(Numeric left, Numeric right) inline double* xlim() { detail::_interpreter::get(); - PyObject* args = PyTuple_New(0); PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args); PyObject* left = PyTuple_GetItem(res,0); @@ -1645,7 +1730,6 @@ inline double* xlim() inline double* ylim() { detail::_interpreter::get(); - PyObject* args = PyTuple_New(0); PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args); PyObject* left = PyTuple_GetItem(res,0); @@ -1665,6 +1749,7 @@ template inline void xticks(const std::vector &ticks, const std::vector &labels = {}, const std::map& keywords = {}) { assert(labels.size() == 0 || ticks.size() == labels.size()); + detail::_interpreter::get(); detail::_interpreter::get(); @@ -1714,6 +1799,7 @@ template inline void yticks(const std::vector &ticks, const std::vector &labels = {}, const std::map& keywords = {}) { assert(labels.size() == 0 || ticks.size() == labels.size()); + detail::_interpreter::get(); detail::_interpreter::get(); @@ -1820,12 +1906,11 @@ inline void tick_params(const std::map& keywords, cons inline void subplot(long nrows, long ncols, long plot_number) { detail::_interpreter::get(); - // construct positional args PyObject* args = PyTuple_New(3); - PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows)); - PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols)); - PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number)); + PyTuple_SetItem(args, 0, PyLong_FromLong(nrows)); + PyTuple_SetItem(args, 1, PyLong_FromLong(ncols)); + PyTuple_SetItem(args, 2, PyLong_FromLong(plot_number)); PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args); if(!res) throw std::runtime_error("Call to subplot() failed."); @@ -1837,7 +1922,6 @@ inline void subplot(long nrows, long ncols, long plot_number) inline void subplot2grid(long nrows, long ncols, long rowid=0, long colid=0, long rowspan=1, long colspan=1) { detail::_interpreter::get(); - PyObject* shape = PyTuple_New(2); PyTuple_SetItem(shape, 0, PyLong_FromLong(nrows)); PyTuple_SetItem(shape, 1, PyLong_FromLong(ncols)); @@ -1864,7 +1948,6 @@ inline void subplot2grid(long nrows, long ncols, long rowid=0, long colid=0, lon inline void title(const std::string &titlestr, const std::map &keywords = {}) { detail::_interpreter::get(); - PyObject* pytitlestr = PyString_FromString(titlestr.c_str()); PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, pytitlestr); @@ -1885,7 +1968,6 @@ inline void title(const std::string &titlestr, const std::map &keywords = {}) { detail::_interpreter::get(); - PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str()); PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, pysuptitlestr); @@ -1906,7 +1988,6 @@ inline void suptitle(const std::string &suptitlestr, const std::map &keywords = {}) { detail::_interpreter::get(); - PyObject* pystr = PyString_FromString(str.c_str()); PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, pystr); @@ -1993,7 +2073,6 @@ inline void xlabel(const std::string &str, const std::map& keywords = {}) { detail::_interpreter::get(); - PyObject* pystr = PyString_FromString(str.c_str()); PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, pystr); @@ -2066,7 +2145,6 @@ inline void set_zlabel(const std::string &str, const std::map inline void pause(Numeric interval) { detail::_interpreter::get(); - PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval)); @@ -2166,7 +2240,6 @@ inline void pause(Numeric interval) inline void save(const std::string& filename) { detail::_interpreter::get(); - PyObject* pyfilename = PyString_FromString(filename.c_str()); PyObject* args = PyTuple_New(1); @@ -2183,8 +2256,8 @@ inline void clf() { detail::_interpreter::get(); PyObject *res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_clf, - detail::_interpreter::get().s_python_empty_tuple); + detail::_interpreter::get().s_python_function_clf, + detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to clf() failed."); @@ -2207,8 +2280,8 @@ inline void ion() { detail::_interpreter::get(); PyObject *res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_ion, - detail::_interpreter::get().s_python_empty_tuple); + detail::_interpreter::get().s_python_function_ion, + detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to ion() failed."); @@ -2218,7 +2291,6 @@ inline void ion() { inline std::vector> ginput(const int numClicks = 1, const std::map& keywords = {}) { detail::_interpreter::get(); - PyObject *args = PyTuple_New(1); PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks)); @@ -2254,10 +2326,9 @@ inline std::vector> ginput(const int numClicks = 1, const // Actually, is there any reason not to call this automatically for every plot? inline void tight_layout() { detail::_interpreter::get(); - PyObject *res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_tight_layout, - detail::_interpreter::get().s_python_empty_tuple); + detail::_interpreter::get().s_python_function_tight_layout, + detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to tight_layout() failed."); @@ -2283,7 +2354,9 @@ struct is_callable_impl template struct is_callable_impl { - struct Fallback { void operator()(); }; + struct Fallback { + void operator()(); + }; struct Derived : T, Fallback { }; template struct Check; @@ -2320,6 +2393,7 @@ struct plot_impl using std::distance; using std::begin; using std::end; + detail::_interpreter::get(); auto xs = distance(begin(x), end(x)); auto ys = distance(begin(y), end(y)); @@ -2369,7 +2443,9 @@ struct plot_impl // recursion stop for the above template -bool plot() { return true; } +bool plot() { + return true; +} template bool plot(const A& a, const B& b, const std::string& format, Args... args) @@ -2405,7 +2481,7 @@ class Plot detail::_interpreter::get(); assert(x.size() == y.size()); - + detail::_interpreter::get(); PyObject* kwargs = PyDict_New(); if(name != "") PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); @@ -2440,7 +2516,9 @@ class Plot // shorter initialization with name or format only // basically calls line, = plot([], []) Plot(const std::string& name = "", const std::string& format = "") - : Plot(name, std::vector(), std::vector(), format) {} + : Plot(name, std::vector(), std::vector(), format) { + detail::_interpreter::get(); + } template bool update(const std::vector& x, const std::vector& y) {