diff --git a/matplotlibcpp.h b/matplotlibcpp.h index c4b27678..d13300e1 100644 --- a/matplotlibcpp.h +++ b/matplotlibcpp.h @@ -49,6 +49,7 @@ struct _interpreter { PyObject *s_python_function_ion; PyObject *s_python_function_ylim; PyObject *s_python_function_title; + PyObject *s_python_function_suptitle; PyObject *s_python_function_axis; PyObject *s_python_function_xlabel; PyObject *s_python_function_ylabel; @@ -62,6 +63,8 @@ struct _interpreter { PyObject *s_python_empty_tuple; PyObject *s_python_function_stem; PyObject *s_python_function_xkcd; + PyObject *s_python_function_axhline; + PyObject *s_python_function_axvline; /* For now, _interpreter is implemented as a singleton since its currently not possible to have multiple independent embedded python interpreters without patching the python source code @@ -150,6 +153,7 @@ struct _interpreter { s_python_function_legend = PyObject_GetAttrString(pymod, "legend"); s_python_function_ylim = PyObject_GetAttrString(pymod, "ylim"); s_python_function_title = PyObject_GetAttrString(pymod, "title"); + s_python_function_suptitle = PyObject_GetAttrString(pymod, "suptitle"); s_python_function_axis = PyObject_GetAttrString(pymod, "axis"); s_python_function_xlabel = PyObject_GetAttrString(pymod, "xlabel"); s_python_function_ylabel = PyObject_GetAttrString(pymod, "ylabel"); @@ -165,6 +169,8 @@ struct _interpreter { s_python_function_tight_layout = PyObject_GetAttrString(pymod, "tight_layout"); s_python_function_stem = PyObject_GetAttrString(pymod, "stem"); s_python_function_xkcd = PyObject_GetAttrString(pymod, "xkcd"); + s_python_function_axhline = PyObject_GetAttrString(pymod, "axhline"); + s_python_function_axvline = PyObject_GetAttrString(pymod, "axvline"); if( !s_python_function_show || !s_python_function_close @@ -181,6 +187,7 @@ struct _interpreter { || !s_python_function_legend || !s_python_function_ylim || !s_python_function_title + || !s_python_function_suptitle || !s_python_function_axis || !s_python_function_xlabel || !s_python_function_ylabel @@ -195,6 +202,8 @@ struct _interpreter { || !s_python_function_tight_layout || !s_python_function_stem || !s_python_function_xkcd + || !s_python_function_axhline + || !s_python_function_axvline ) { throw std::runtime_error("Couldn't find required function!"); } if ( !PyFunction_Check(s_python_function_show) @@ -213,6 +222,7 @@ struct _interpreter { || !PyFunction_Check(s_python_function_annotate) || !PyFunction_Check(s_python_function_ylim) || !PyFunction_Check(s_python_function_title) + || !PyFunction_Check(s_python_function_suptitle) || !PyFunction_Check(s_python_function_axis) || !PyFunction_Check(s_python_function_xlabel) || !PyFunction_Check(s_python_function_ylabel) @@ -225,6 +235,8 @@ struct _interpreter { || !PyFunction_Check(s_python_function_errorbar) || !PyFunction_Check(s_python_function_stem) || !PyFunction_Check(s_python_function_xkcd) + || !PyFunction_Check(s_python_function_axhline) + || !PyFunction_Check(s_python_function_axvline) ) { throw std::runtime_error("Python object is unexpectedly not a PyFunction."); } s_python_empty_tuple = PyTuple_New(0); @@ -463,23 +475,27 @@ 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 = "") +bool plot(const std::vector& x, const std::vector& y, const std::string& format = "", const std::string& color = "") { assert(x.size() == y.size()); PyObject* xarray = get_array(x); PyObject* yarray = get_array(y); - PyObject* pystring = PyString_FromString(s.c_str()); + PyObject* pyformat = PyString_FromString(format.c_str()); PyObject* plot_args = PyTuple_New(3); PyTuple_SetItem(plot_args, 0, xarray); PyTuple_SetItem(plot_args, 1, yarray); - PyTuple_SetItem(plot_args, 2, pystring); + PyTuple_SetItem(plot_args, 2, pyformat); + + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); + PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); Py_DECREF(plot_args); + Py_DECREF(kwargs); if(res) Py_DECREF(res); return res; @@ -648,10 +664,11 @@ bool errorbar(const std::vector &x, const std::vector &y, co } template -bool named_plot(const std::string& name, const std::vector& y, const std::string& format = "") +bool named_plot(const std::string& name, const std::vector& y, const std::string& format = "", const std::string& color = "") { PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); PyObject* yarray = get_array(y); @@ -672,10 +689,11 @@ bool named_plot(const std::string& name, const std::vector& y, const st } template -bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") +bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "", const std::string& color = "") { PyObject* kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); PyObject* xarray = get_array(x); PyObject* yarray = get_array(y); @@ -1015,6 +1033,19 @@ inline void title(const std::string &titlestr) Py_DECREF(res); } +inline void suptitle(const std::string &suptitlestr) +{ + PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str()); + PyObject* args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pysuptitlestr); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_suptitle, args); + if(!res) throw std::runtime_error("Call to suptitle() failed."); + + Py_DECREF(args); + Py_DECREF(res); +} + inline void axis(const std::string &axisstr) { PyObject* str = PyString_FromString(axisstr.c_str()); @@ -1113,7 +1144,55 @@ inline void xkcd() { Py_DECREF(kwargs); if (!res) - throw std::runtime_error("Call to show() failed."); + throw std::runtime_error("Call to xkcd() failed."); + + Py_DECREF(res); +} + +inline void axhline(const double y = 0, const std::string& linestyle = "", const std::string &color = "", const double xmin = 0, const double xmax = 1) { + PyObject *res; + PyObject *args = PyTuple_New(3); + PyObject *kwargs = PyDict_New(); + + PyDict_SetItemString(kwargs, "linestyle", PyString_FromString(linestyle.c_str())); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); + + PyTuple_SetItem(args, 0, PyFloat_FromDouble(y)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmin)); + PyTuple_SetItem(args, 2, PyFloat_FromDouble(xmax)); + + res = PyObject_Call(detail::_interpreter::get().s_python_function_axhline, + args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if (!res) + throw std::runtime_error("Call to axhline() failed."); + + Py_DECREF(res); +} + +inline void axvline(const double x = 0, const std::string& linestyle = "", const std::string &color = "", const double ymin = 0, const double ymax = 1) { + PyObject *res; + PyObject *args = PyTuple_New(3); + PyObject *kwargs = PyDict_New(); + + PyDict_SetItemString(kwargs, "linestyle", PyString_FromString(linestyle.c_str())); + PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str())); + + PyTuple_SetItem(args, 0, PyFloat_FromDouble(x)); + PyTuple_SetItem(args, 1, PyFloat_FromDouble(ymin)); + PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymax)); + + res = PyObject_Call(detail::_interpreter::get().s_python_function_axvline, + args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + + if (!res) + throw std::runtime_error("Call to axvline() failed."); Py_DECREF(res); } @@ -1166,7 +1245,7 @@ inline void clf() { Py_DECREF(res); } - inline void ion() { +inline void ion() { PyObject *res = PyObject_CallObject( detail::_interpreter::get().s_python_function_ion, detail::_interpreter::get().s_python_empty_tuple);