Skip to content

Commit b568e87

Browse files
committed
add contour plot, add support for keywords in scatter
1 parent bd05374 commit b568e87

File tree

4 files changed

+131
-3
lines changed

4 files changed

+131
-3
lines changed

examples/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ endfunction(add_example)
1616
add_example(axlines)
1717
add_example(bar)
1818
add_example(basic)
19+
add_example(contour)
1920
add_example(eigen)
2021
add_example(errorbar)
2122
add_example(fill_inbetween)
@@ -26,6 +27,7 @@ add_example(minimal)
2627
add_example(modern)
2728
add_example(nonblock)
2829
add_example(quiver)
30+
add_example(scatter)
2931
add_example(semilogx)
3032
add_example(semilogy)
3133
add_example(small)

examples/contour.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <Eigen/Dense>
2+
#include "../matplotlibcpp.h"
3+
namespace plt = matplotlibcpp;
4+
5+
template <typename Vector>
6+
std::pair<Eigen::MatrixXd, Eigen::MatrixXd> meshgrid(const Vector& x, const Vector& y) {
7+
const unsigned m = x.size(), n = y.size();
8+
// todo fix type
9+
Eigen::MatrixXd X(m, n), Y(m, n);
10+
for (unsigned i = 0; i < m; ++i) {
11+
for (unsigned j = 0; j < n; ++ j) {
12+
X(i, j) = *(x.data() + i);
13+
Y(i, j) = *(y.data() + j);
14+
}
15+
}
16+
std::pair<Eigen::MatrixXd, Eigen::MatrixXd> res = std::make_pair(X, Y);
17+
return res;
18+
}
19+
20+
void plot_contour() {
21+
const unsigned n = 100;
22+
Eigen::VectorXd x = Eigen::VectorXd::LinSpaced(n, 0, 1),
23+
y = Eigen::VectorXd::LinSpaced(n, 0, 1);
24+
std::pair<Eigen::MatrixXd, Eigen::MatrixXd> XY = meshgrid(x, y);
25+
Eigen::MatrixXd Z = XY.first + 2 * XY.second;
26+
27+
plt::contour(XY.first, XY.second, Z);
28+
plt::show();
29+
30+
}
31+
32+
int main() {
33+
plot_contour();
34+
return 0;
35+
}

examples/scatter.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#define _USE_MATH_DEFINES
2+
#include <cmath>
3+
#include <vector>
4+
#include "../matplotlibcpp.h"
5+
namespace plt = matplotlibcpp;
6+
7+
void plot() {
8+
const unsigned n = 100;
9+
std::vector<double> x(n), y(n);
10+
11+
#include <iostream>
12+
for (unsigned i = 0; i < n; ++i) {
13+
x[i] = sin(2 * M_PI * i / n);
14+
y[i] = cos(2 * M_PI * i / n);
15+
}
16+
17+
plt::scatter(x, y, {{"color", "red"}, {"label", "a circle!"}});
18+
plt::legend();
19+
plt::show();
20+
}
21+
22+
int main() {
23+
plot();
24+
return 0;
25+
}

matplotlibcpp.h

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
763815
template <typename Numeric>
764816
bool 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
897950
template <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

Comments
 (0)