@@ -102,6 +102,7 @@ struct _interpreter {
102102 PyObject *s_python_function_colorbar;
103103 PyObject *s_python_function_subplots_adjust;
104104 PyObject *s_python_function_rcparams;
105+ PyObject *s_python_function_spy;
105106
106107 /* For now, _interpreter is implemented as a singleton since its currently not possible to have
107108 multiple independent embedded python interpreters without patching the python source code
@@ -276,6 +277,7 @@ struct _interpreter {
276277 s_python_function_colorbar = PyObject_GetAttrString (pymod, " colorbar" );
277278 s_python_function_subplots_adjust = safe_import (pymod," subplots_adjust" );
278279 s_python_function_rcparams = PyObject_GetAttrString (pymod, " rcParams" );
280+ s_python_function_spy = PyObject_GetAttrString (pymod, " spy" );
279281#ifndef WITHOUT_NUMPY
280282 s_python_function_imshow = safe_import (pymod, " imshow" );
281283#endif
@@ -348,11 +350,11 @@ template <> struct select_npy_type<uint64_t> { const static NPY_TYPES type = NPY
348350
349351// Sanity checks; comment them out or change the numpy type below if you're compiling on
350352// a platform where they don't apply
351- // static_assert(sizeof(long long) == 8);
352- // template <> struct select_npy_type<long long> { const static NPY_TYPES type = NPY_INT64; };
353- // static_assert(sizeof(unsigned long long) == 8);
354- // template <> struct select_npy_type<unsigned long long> { const static NPY_TYPES type = NPY_UINT64; };
355- // TODO: add int, long, etc.
353+ static_assert (sizeof (long long ) == 8 );
354+ template <> struct select_npy_type <long long > { const static NPY_TYPES type = NPY_INT64; };
355+ static_assert (sizeof (unsigned long long ) == 8 );
356+ template <> struct select_npy_type <unsigned long long > { const static NPY_TYPES type = NPY_UINT64; };
357+ TODO: add int , long , etc.
356358
357359template <typename Numeric>
358360PyObject* get_array (const std::vector<Numeric>& v)
@@ -621,8 +623,37 @@ void contour(const std::vector<::std::vector<Numeric>> &x,
621623
622624 Py_DECREF (args);
623625 Py_DECREF (kwargs);
624- if (res)
625- Py_DECREF (res);
626+ if (res) Py_DECREF (res);
627+ }
628+
629+ template <typename Numeric>
630+ void spy (const std::vector<::std::vector<Numeric>> &x,
631+ const double markersize = -1 , // -1 for default matplotlib size
632+ const std::map<std::string, std::string> &keywords = {})
633+ {
634+ detail::_interpreter::get ();
635+
636+ PyObject *xarray = detail::get_2darray (x);
637+
638+ PyObject *kwargs = PyDict_New ();
639+ if (markersize != -1 ) {
640+ PyDict_SetItemString (kwargs, " markersize" , PyFloat_FromDouble (markersize));
641+ }
642+ for (std::map<std::string, std::string>::const_iterator it = keywords.begin ();
643+ it != keywords.end (); ++it) {
644+ PyDict_SetItemString (kwargs, it->first .c_str (),
645+ PyString_FromString (it->second .c_str ()));
646+ }
647+
648+ PyObject *plot_args = PyTuple_New (1 );
649+ PyTuple_SetItem (plot_args, 0 , xarray);
650+
651+ PyObject *res = PyObject_Call (
652+ detail::_interpreter::get ().s_python_function_spy , plot_args, kwargs);
653+
654+ Py_DECREF (plot_args);
655+ Py_DECREF (kwargs);
656+ if (res) Py_DECREF (res);
626657}
627658#endif // WITHOUT_NUMPY
628659
0 commit comments