@@ -95,6 +95,7 @@ struct _interpreter {
9595 PyObject *s_python_function_colorbar;
9696 PyObject *s_python_function_subplots_adjust;
9797 PyObject *s_python_function_contour;
98+ PyObject *s_python_function_spy;
9899
99100
100101 /* For now, _interpreter is implemented as a singleton since its currently not possible to have
@@ -233,9 +234,10 @@ struct _interpreter {
233234 s_python_function_bar = safe_import (pymod," bar" );
234235 s_python_function_colorbar = PyObject_GetAttrString (pymod, " colorbar" );
235236 s_python_function_subplots_adjust = safe_import (pymod," subplots_adjust" );
236- s_python_function_contour = safe_import (pymod, " contour" );
237237#ifndef WITHOUT_NUMPY
238+ s_python_function_contour = safe_import (pymod, " contour" );
238239 s_python_function_imshow = safe_import (pymod, " imshow" );
240+ s_python_function_spy = safe_import (pymod, " spy" );
239241#endif
240242 s_python_empty_tuple = PyTuple_New (0 );
241243 }
@@ -306,11 +308,11 @@ template <> struct select_npy_type<uint64_t> { const static NPY_TYPES type = NPY
306308
307309// Sanity checks; comment them out or change the numpy type below if you're compiling on
308310// a platform where they don't apply
309- // static_assert(sizeof(long long) == 8);
310- // template <> struct select_npy_type<long long> { const static NPY_TYPES type = NPY_INT64; };
311- // static_assert(sizeof(unsigned long long) == 8);
312- // template <> struct select_npy_type<unsigned long long> { const static NPY_TYPES type = NPY_UINT64; };
313- // TODO: add int, long, etc.
311+ static_assert (sizeof (long long ) == 8 );
312+ template <> struct select_npy_type <long long > { const static NPY_TYPES type = NPY_INT64 ; };
313+ static_assert (sizeof (unsigned long long ) == 8 );
314+ template <> struct select_npy_type <unsigned long long > { const static NPY_TYPES type = NPY_UINT64 ; };
315+ TODO : add int , long , etc.
314316
315317template <typename Numeric>
316318PyObject* get_array (const std::vector<Numeric>& v)
@@ -563,8 +565,37 @@ void contour(const std::vector<::std::vector<Numeric>> &x,
563565
564566 Py_DECREF (args);
565567 Py_DECREF (kwargs);
566- if (res)
567- Py_DECREF (res);
568+ if (res) Py_DECREF (res);
569+ }
570+
571+ template <typename Numeric>
572+ void spy (const std::vector<::std::vector<Numeric>> &x,
573+ const double markersize = -1 , // -1 for default matplotlib size
574+ const std::map<std::string, std::string> &keywords = {})
575+ {
576+ detail::_interpreter::get ();
577+
578+ PyObject *xarray = detail::get_2darray (x);
579+
580+ PyObject *kwargs = PyDict_New ();
581+ if (markersize != -1 ) {
582+ PyDict_SetItemString (kwargs, " markersize" , PyFloat_FromDouble (markersize));
583+ }
584+ for (std::map<std::string, std::string>::const_iterator it = keywords.begin ();
585+ it != keywords.end (); ++it) {
586+ PyDict_SetItemString (kwargs, it->first .c_str (),
587+ PyString_FromString (it->second .c_str ()));
588+ }
589+
590+ PyObject *plot_args = PyTuple_New (1 );
591+ PyTuple_SetItem (plot_args, 0 , xarray);
592+
593+ PyObject *res = PyObject_Call (
594+ detail::_interpreter::get ().s_python_function_spy , plot_args, kwargs);
595+
596+ Py_DECREF (plot_args);
597+ Py_DECREF (kwargs);
598+ if (res) Py_DECREF (res);
568599}
569600#endif // WITHOUT_NUMPY
570601
0 commit comments