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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy