diff --git a/README.md b/README.md index 8534597d..f7fa1258 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,36 @@ int main() Result: ![Modern example](./examples/modern.png) +Or some *funny-looking xkcd-styled* example: +```cpp +#include "matplotlibcpp.h" +#include +#include + +namespace plt = matplotlibcpp; + +int main() { + std::vector t(1000); + std::vector x(t.size()); + + for(size_t i = 0; i < t.size(); i++) { + t[i] = i / 100.0; + x[i] = sin(2.0 * M_PI * 1.0 * t[i]); + } + + plt::xkcd(); + plt::plot(t, x); + plt::title("AN ORDINARY SIN WAVE"); + plt::save("xkcd.png"); +} + +``` + g++ xkcd.cpp -std=c++11 -I/usr/include/python2.7 -lpython2.7 + +**Result:** + +![Minimal example](./examples/xkcd.png) + Installation ------------ diff --git a/examples/xkcd.cpp b/examples/xkcd.cpp new file mode 100644 index 00000000..3778175e --- /dev/null +++ b/examples/xkcd.cpp @@ -0,0 +1,21 @@ +#include "../matplotlibcpp.h" +#include +#include + +namespace plt = matplotlibcpp; + +int main() { + std::vector t(1000); + std::vector x(t.size()); + + for(size_t i = 0; i < t.size(); i++) { + t[i] = i / 100.0; + x[i] = sin(2.0 * M_PI * 1.0 * t[i]); + } + + plt::xkcd(); + plt::plot(t, x); + plt::title("AN ORDINARY SIN WAVE"); + plt::save("xkcd.png"); +} + diff --git a/examples/xkcd.png b/examples/xkcd.png new file mode 100644 index 00000000..c285e3d8 Binary files /dev/null and b/examples/xkcd.png differ diff --git a/matplotlibcpp.h b/matplotlibcpp.h index 638a2726..33e63b67 100644 --- a/matplotlibcpp.h +++ b/matplotlibcpp.h @@ -55,6 +55,8 @@ namespace matplotlibcpp { PyObject *s_python_function_annotate; PyObject *s_python_function_tight_layout; PyObject *s_python_empty_tuple; + PyObject *s_python_function_stem; + PyObject *s_python_function_xkcd; /* 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 @@ -133,6 +135,8 @@ namespace matplotlibcpp { s_python_function_clf = PyObject_GetAttrString(pymod, "clf"); s_python_function_errorbar = PyObject_GetAttrString(pymod, "errorbar"); 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"); if( !s_python_function_show || !s_python_function_draw @@ -158,6 +162,8 @@ namespace matplotlibcpp { || !s_python_function_errorbar || !s_python_function_errorbar || !s_python_function_tight_layout + || !s_python_function_stem + || !s_python_function_xkcd ) { throw std::runtime_error("Couldn't find required function!"); } if ( !PyFunction_Check(s_python_function_show) @@ -183,6 +189,8 @@ namespace matplotlibcpp { || !PyFunction_Check(s_python_function_clf) || !PyFunction_Check(s_python_function_tight_layout) || !PyFunction_Check(s_python_function_errorbar) + || !PyFunction_Check(s_python_function_stem) + || !PyFunction_Check(s_python_function_xkcd) ) { throw std::runtime_error("Python object is unexpectedly not a PyFunction."); } s_python_empty_tuple = PyTuple_New(0); @@ -302,6 +310,39 @@ namespace matplotlibcpp { return res; } + template + bool stem(const std::vector &x, const std::vector &y, const std::map& keywords) + { + assert(x.size() == y.size()); + + // using numpy arrays + PyObject* xarray = get_array(x); + PyObject* yarray = get_array(y); + + // construct positional args + PyObject* args = PyTuple_New(2); + PyTuple_SetItem(args, 0, xarray); + PyTuple_SetItem(args, 1, yarray); + + // construct keyword args + PyObject* kwargs = PyDict_New(); + for (std::map::const_iterator it = + keywords.begin(); it != keywords.end(); ++it) { + PyDict_SetItemString(kwargs, it->first.c_str(), + PyString_FromString(it->second.c_str())); + } + + PyObject* res = PyObject_Call( + detail::_interpreter::get().s_python_function_stem, args, kwargs); + + Py_DECREF(args); + Py_DECREF(kwargs); + if (res) + Py_DECREF(res); + + return res; + } + template< typename Numeric > bool fill_between(const std::vector& x, const std::vector& y1, const std::vector& y2, const std::map& keywords) { @@ -409,6 +450,31 @@ namespace matplotlibcpp { return res; } + template + bool stem(const std::vector& x, const std::vector& y, const std::string& s = "") + { + assert(x.size() == y.size()); + + PyObject* xarray = get_array(x); + PyObject* yarray = get_array(y); + + PyObject* pystring = PyString_FromString(s.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); + + PyObject* res = PyObject_CallObject( + detail::_interpreter::get().s_python_function_stem, plot_args); + + Py_DECREF(plot_args); + if (res) + Py_DECREF(res); + + return res; + } + template bool semilogx(const std::vector& x, const std::vector& y, const std::string& s = "") { @@ -642,6 +708,14 @@ namespace matplotlibcpp { return plot(x,y,format); } + template + bool stem(const std::vector& y, const std::string& format = "") + { + std::vector x(y.size()); + for (size_t i = 0; i < x.size(); ++i) x.at(i) = i; + return stem(x, y, format); + } + inline void figure() { PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, detail::_interpreter::get().s_python_empty_tuple); @@ -826,6 +900,19 @@ namespace matplotlibcpp { Py_DECREF(res); } + inline void xkcd() { + PyObject* res; + PyObject *kwargs = PyDict_New(); + + res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd, + detail::_interpreter::get().s_python_empty_tuple, kwargs); + + if (!res) + throw std::runtime_error("Call to show() failed."); + + Py_DECREF(res); + } + inline void draw() { PyObject* res = PyObject_CallObject( @@ -1015,6 +1102,21 @@ namespace matplotlibcpp { return plot(x,y,keywords); } + bool stem(const std::vector& x, const std::vector& y, const std::string& format = "") + { + return stem(x, y, format); + } + + bool stem(const std::vector& y, const std::string& format = "") + { + return stem(y, format); + } + + bool stem(const std::vector& x, const std::vector& y, const std::map& keywords) + { + return stem(x, y, keywords); + } + bool named_plot(const std::string& name, const std::vector& x, const std::vector& y, const std::string& format = "") { return named_plot(name,x,y,format); }