@@ -53,6 +53,8 @@ struct _interpreter {
5353 PyObject *s_python_function_fignum_exists;
5454 PyObject *s_python_function_plot;
5555 PyObject *s_python_function_quiver;
56+ PyObject *s_python_function_contour;
57+ PyObject *s_python_function_colormap;
5658 PyObject *s_python_function_axhline;
5759 PyObject *s_python_function_axvline;
5860 PyObject *s_python_function_semilogx;
@@ -184,6 +186,7 @@ struct _interpreter {
184186 PyObject_GetAttrString (pymod, " fignum_exists" );
185187 s_python_function_plot = PyObject_GetAttrString (pymod, " plot" );
186188 s_python_function_quiver = PyObject_GetAttrString (pymod, " quiver" );
189+ s_python_function_contour = PyObject_GetAttrString (pymod, " contour" );
187190 s_python_function_axhline = PyObject_GetAttrString (pymod, " axhline" );
188191 s_python_function_axvline = PyObject_GetAttrString (pymod, " axvline" );
189192 s_python_function_semilogx = PyObject_GetAttrString (pymod, " semilogx" );
@@ -228,6 +231,7 @@ struct _interpreter {
228231 !s_python_function_draw || !s_python_function_pause ||
229232 !s_python_function_figure || !s_python_function_fignum_exists ||
230233 !s_python_function_plot || !s_python_function_quiver ||
234+ !s_python_function_contour ||
231235 !s_python_function_semilogx || !s_python_function_semilogy ||
232236 !s_python_function_loglog || !s_python_function_fill ||
233237 !s_python_function_fill_between || !s_python_function_subplot ||
@@ -256,6 +260,7 @@ struct _interpreter {
256260 !PyFunction_Check (s_python_function_fignum_exists) ||
257261 !PyFunction_Check (s_python_function_plot) ||
258262 !PyFunction_Check (s_python_function_quiver) ||
263+ !PyFunction_Check (s_python_function_contour) ||
259264 !PyFunction_Check (s_python_function_semilogx) ||
260265 !PyFunction_Check (s_python_function_semilogy) ||
261266 !PyFunction_Check (s_python_function_loglog) ||
@@ -760,6 +765,53 @@ void plot_surface(const Matrix &x, const Matrix& y, const Matrix& z,
760765 Py_DECREF (res);
761766}
762767
768+
769+ // @brief plot_surface for datapoints (x_ij, y_ij, z_ij) with i,j = 0..n
770+ // @param x The x values of the datapoints in a matrix
771+ // @param y The y values of the datapoints in a matrix
772+ // @param z The function value of the datapoints in a matrix
773+ // @param keywords Additional keywords
774+ template <typename Matrix>
775+ void contour (const Matrix &x, const Matrix& y, const Matrix& z,
776+ const std::map<std::string, std::string> &keywords = {}) {
777+ detail::_interpreter::get ();
778+
779+ // using numpy arrays
780+ PyObject *xarray = get_2darray (x);
781+ PyObject *yarray = get_2darray (y);
782+ PyObject *zarray = get_2darray (z);
783+
784+ // construct positional args
785+ PyObject *args = PyTuple_New (3 );
786+ PyTuple_SetItem (args, 0 , xarray);
787+ PyTuple_SetItem (args, 1 , yarray);
788+ PyTuple_SetItem (args, 2 , zarray);
789+
790+ // Build up the kw args.
791+ PyObject *kwargs = PyDict_New ();
792+
793+ PyObject *python_colormap_coolwarm = PyObject_GetAttrString (
794+ detail::_interpreter::get ().s_python_colormap , " coolwarm" );
795+
796+ PyDict_SetItemString (kwargs, " cmap" , python_colormap_coolwarm);
797+
798+ for (std::map<std::string, std::string>::const_iterator it = keywords.begin ();
799+ it != keywords.end (); ++it) {
800+ PyDict_SetItemString (kwargs, it->first .c_str (),
801+ PyString_FromString (it->second .c_str ()));
802+ }
803+
804+ PyObject *res = PyObject_Call (detail::_interpreter::get ().s_python_function_contour ,
805+ args, kwargs);
806+ if (!res)
807+ throw std::runtime_error (" failed surface" );
808+
809+ Py_DECREF (args);
810+ Py_DECREF (kwargs);
811+ if (res)
812+ Py_DECREF (res);
813+ }
814+
763815template <typename Numeric>
764816bool stem (const std::vector<Numeric> &x, const std::vector<Numeric> &y,
765817 const std::map<std::string, std::string> &keywords) {
@@ -893,16 +945,23 @@ bool hist(const VectorY &y, long bins = 10, std::string color = "b",
893945// @brief Scatter plot
894946// @param x x-coordinates of the 2d points
895947// @param y y-coordinates of the 2d points
896- // @param s the marker size in points**2
948+ // @param s the marker size in points**2
949+ // @param keywords Additional keywords
897950template <typename VectorX, typename VectorY>
898- bool scatter (const VectorX &x, const VectorY &y, const double s = 1.0 ) {
951+ bool scatter (const VectorX &x, const VectorY &y, const double s = 1.0 ,
952+ const std::map<std::string, std::string> keywords = {}) {
899953 assert (x.size () == y.size ());
900954
901955 PyObject *xarray = get_array (x);
902956 PyObject *yarray = get_array (y);
903957
904958 PyObject *kwargs = PyDict_New ();
905- PyDict_SetItemString (kwargs, " s" , PyLong_FromLong (s));
959+ PyDict_SetItemString (kwargs, " s" , PyFloat_FromDouble (s));
960+ for (std::map<std::string, std::string>::const_iterator it = keywords.begin ();
961+ it != keywords.end (); ++it) {
962+ PyDict_SetItemString (kwargs, it->first .c_str (),
963+ PyUnicode_FromString (it->second .c_str ()));
964+ }
906965
907966 PyObject *plot_args = PyTuple_New (2 );
908967 PyTuple_SetItem (plot_args, 0 , xarray);
@@ -919,6 +978,13 @@ bool scatter(const VectorX &x, const VectorY &y, const double s = 1.0) {
919978 return res;
920979}
921980
981+ template <typename VectorX, typename VectorY>
982+ bool scatter (const VectorX &x, const VectorY &y,
983+ const std::map<std::string, std::string>& keywords) {
984+ return scatter (x, y, 1.0 , keywords);
985+ }
986+
987+
922988// @brief Spy plot
923989// @param A the matrix
924990// @param precision Plot all elements above `|precision|`
0 commit comments