@@ -55,6 +55,8 @@ namespace matplotlibcpp {
5555 PyObject *s_python_function_annotate;
5656 PyObject *s_python_function_tight_layout;
5757 PyObject *s_python_empty_tuple;
58+ PyObject *s_python_function_stem;
59+ PyObject *s_python_function_xkcd;
5860
5961 /* For now, _interpreter is implemented as a singleton since its currently not possible to have
6062 multiple independent embedded python interpreters without patching the python source code
@@ -133,6 +135,8 @@ namespace matplotlibcpp {
133135 s_python_function_clf = PyObject_GetAttrString (pymod, " clf" );
134136 s_python_function_errorbar = PyObject_GetAttrString (pymod, " errorbar" );
135137 s_python_function_tight_layout = PyObject_GetAttrString (pymod, " tight_layout" );
138+ s_python_function_stem = PyObject_GetAttrString (pymod, " stem" );
139+ s_python_function_xkcd = PyObject_GetAttrString (pymod, " xkcd" );
136140
137141 if ( !s_python_function_show
138142 || !s_python_function_draw
@@ -158,6 +162,8 @@ namespace matplotlibcpp {
158162 || !s_python_function_errorbar
159163 || !s_python_function_errorbar
160164 || !s_python_function_tight_layout
165+ || !s_python_function_stem
166+ || !s_python_function_xkcd
161167 ) { throw std::runtime_error (" Couldn't find required function!" ); }
162168
163169 if ( !PyFunction_Check (s_python_function_show)
@@ -183,6 +189,8 @@ namespace matplotlibcpp {
183189 || !PyFunction_Check (s_python_function_clf)
184190 || !PyFunction_Check (s_python_function_tight_layout)
185191 || !PyFunction_Check (s_python_function_errorbar)
192+ || !PyFunction_Check (s_python_function_stem)
193+ || !PyFunction_Check (s_python_function_xkcd)
186194 ) { throw std::runtime_error (" Python object is unexpectedly not a PyFunction." ); }
187195
188196 s_python_empty_tuple = PyTuple_New (0 );
@@ -302,6 +310,39 @@ namespace matplotlibcpp {
302310 return res;
303311 }
304312
313+ template <typename Numeric>
314+ bool stem (const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
315+ {
316+ assert (x.size () == y.size ());
317+
318+ // using numpy arrays
319+ PyObject* xarray = get_array (x);
320+ PyObject* yarray = get_array (y);
321+
322+ // construct positional args
323+ PyObject* args = PyTuple_New (2 );
324+ PyTuple_SetItem (args, 0 , xarray);
325+ PyTuple_SetItem (args, 1 , yarray);
326+
327+ // construct keyword args
328+ PyObject* kwargs = PyDict_New ();
329+ for (std::map<std::string, std::string>::const_iterator it =
330+ keywords.begin (); it != keywords.end (); ++it) {
331+ PyDict_SetItemString (kwargs, it->first .c_str (),
332+ PyString_FromString (it->second .c_str ()));
333+ }
334+
335+ PyObject* res = PyObject_Call (
336+ detail::_interpreter::get ().s_python_function_stem , args, kwargs);
337+
338+ Py_DECREF (args);
339+ Py_DECREF (kwargs);
340+ if (res)
341+ Py_DECREF (res);
342+
343+ return res;
344+ }
345+
305346 template < typename Numeric >
306347 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)
307348 {
@@ -409,6 +450,31 @@ namespace matplotlibcpp {
409450 return res;
410451 }
411452
453+ template <typename NumericX, typename NumericY>
454+ bool stem (const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = " " )
455+ {
456+ assert (x.size () == y.size ());
457+
458+ PyObject* xarray = get_array (x);
459+ PyObject* yarray = get_array (y);
460+
461+ PyObject* pystring = PyString_FromString (s.c_str ());
462+
463+ PyObject* plot_args = PyTuple_New (3 );
464+ PyTuple_SetItem (plot_args, 0 , xarray);
465+ PyTuple_SetItem (plot_args, 1 , yarray);
466+ PyTuple_SetItem (plot_args, 2 , pystring);
467+
468+ PyObject* res = PyObject_CallObject (
469+ detail::_interpreter::get ().s_python_function_stem , plot_args);
470+
471+ Py_DECREF (plot_args);
472+ if (res)
473+ Py_DECREF (res);
474+
475+ return res;
476+ }
477+
412478 template <typename NumericX, typename NumericY>
413479 bool semilogx (const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = " " )
414480 {
@@ -642,6 +708,14 @@ namespace matplotlibcpp {
642708 return plot (x,y,format);
643709 }
644710
711+ template <typename Numeric>
712+ bool stem (const std::vector<Numeric>& y, const std::string& format = " " )
713+ {
714+ std::vector<Numeric> x (y.size ());
715+ for (size_t i = 0 ; i < x.size (); ++i) x.at (i) = i;
716+ return stem (x, y, format);
717+ }
718+
645719 inline void figure ()
646720 {
647721 PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_figure , detail::_interpreter::get ().s_python_empty_tuple );
@@ -826,6 +900,19 @@ namespace matplotlibcpp {
826900 Py_DECREF (res);
827901 }
828902
903+ inline void xkcd () {
904+ PyObject* res;
905+ PyObject *kwargs = PyDict_New ();
906+
907+ res = PyObject_Call (detail::_interpreter::get ().s_python_function_xkcd ,
908+ detail::_interpreter::get ().s_python_empty_tuple , kwargs);
909+
910+ if (!res)
911+ throw std::runtime_error (" Call to show() failed." );
912+
913+ Py_DECREF (res);
914+ }
915+
829916 inline void draw ()
830917 {
831918 PyObject* res = PyObject_CallObject (
@@ -1015,6 +1102,21 @@ namespace matplotlibcpp {
10151102 return plot<double >(x,y,keywords);
10161103 }
10171104
1105+ bool stem (const std::vector<double >& x, const std::vector<double >& y, const std::string& format = " " )
1106+ {
1107+ return stem<double , double >(x, y, format);
1108+ }
1109+
1110+ bool stem (const std::vector<double >& y, const std::string& format = " " )
1111+ {
1112+ return stem<double >(y, format);
1113+ }
1114+
1115+ bool stem (const std::vector<double >& x, const std::vector<double >& y, const std::map<std::string, std::string>& keywords)
1116+ {
1117+ return stem<double >(x, y, keywords);
1118+ }
1119+
10181120 bool named_plot (const std::string& name, const std::vector<double >& x, const std::vector<double >& y, const std::string& format = " " ) {
10191121 return named_plot<double >(name,x,y,format);
10201122 }
0 commit comments