Skip to content
Snippets Groups Projects
Unverified Commit d261c7d6 authored by Mamoru Sobue's avatar Mamoru Sobue Committed by GitHub
Browse files

Merge pull request #16 from soblin/develop

Develop
parents 7e1ab087 0bfe4d49
Branches
No related tags found
No related merge requests found
......@@ -14,7 +14,7 @@ find_package(pybind11 2.4.3 REQUIRED)
# check matplotlib minor version
execute_process(
COMMAND
"python3" "-c"
${Python3_EXECUTABLE} "-c"
"import matplotlib;
print(str(matplotlib.__version__))"
RESULT_VARIABLE MATPLOTLIB_VERSION_CHECKING
......
......
......@@ -13,7 +13,7 @@ It is supposed to provide the user with almost full access to matplotlib feature
- [pybind11](https://github.com/pybind/pybind11) >= 2.4.3
- `sudo apt install pybind11-dev` (on Ubuntu20.04)
- or manual install
- compatible with [matplotlib](https://matplotlib.org/stable/index.html) == 3.5.1
- [matplotlib](https://matplotlib.org/stable/index.html) >= 3.4.0
- numpy for `mplot3d`
- ([xtensor](https://github.com/xtensor-stack/xtensor) == 0.24.0 + [xtl](https://github.com/xtensor-stack/xtl), only for `gallery` demos)
......
......
......@@ -3,18 +3,19 @@
#include <pybind11/embed.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <matplotlibcpp17/pyplot.h>
#include <matplotlibcpp17/patches.h>
#include <algorithm>
#include <iostream>
#include <xtensor/xrandom.hpp>
#include <vector>
namespace py = pybind11;
using namespace py::literals;
using namespace std;
using namespace matplotlibcpp17;
using namespace matplotlibcpp17::patches;
using namespace matplotlibcpp17;
int main() {
......@@ -22,27 +23,30 @@ int main() {
auto plt = matplotlibcpp17::pyplot::import();
auto [fig, ax] = plt.subplots();
const int resolution = 50;
const int N = 3;
vector<double> x = {0.7003673, 0.74275081, 0.70928001},
y = {0.56674552, 0.97778533, 0.70633485},
radii = {0.02479158, 0.01578834, 0.06976985};
xt::xarray<double> x = xt::random::rand<double>({N});
xt::xarray<double> y = xt::random::rand<double>({N});
xt::xarray<double> radii = 0.1 * xt::random::rand<double>({N});
py::list patches; // instead of patches = []
for (int i = 0; i < N; ++i) {
const double x1 = x[i], y1 = y[i], r = radii[i];
auto circle = patches::Circle(Args(py::make_tuple(x1, y1), r));
patches.append(circle.unwrap());
}
x = {0.71995667, 0.25774443, 0.34154678};
y = {0.96876117, 0.6945071, 0.46638326};
radii = {0.07028127, 0.05117859, 0.09287414};
vector<double> theta1 = {266.3169476, 224.07805212, 234.5563688},
theta2 = {142.85074015, 195.56618216, 287.96383014};
x = xt::random::rand<double>({N});
y = xt::random::rand<double>({N});
radii = 0.1 * xt::random::rand<double>({N});
xt::xarray<double> theta1 = 360.0 * xt::random::rand<double>({N});
xt::xarray<double> theta2 = 360.0 * xt::random::rand<double>({N});
for (int i = 0; i < N; ++i) {
const double x1 = x[i], y1 = y[i], r = radii[i], th1 = theta1[i],
th2 = theta2[i];
auto wedge = patches::Wedge(Args(py::make_tuple(x1, y1), r, th1, th2));
patches.append(wedge.unwrap());
}
patches.append(
patches::Wedge(Args(py::make_tuple(0.3, 0.7), 0.1, 0, 360)).unwrap());
patches.append(patches::Wedge(Args(py::make_tuple(0.7, 0.8), 0.2, 0, 360),
......@@ -53,16 +57,30 @@ int main() {
patches.append(patches::Wedge(Args(py::make_tuple(0.8, 0.3), 0.2, 45, 90),
Kwargs("width"_a = 0.10))
.unwrap());
// NOTE: Polygon take numpy array as argument, so skip it
vector<double> colors_ = {90.63036451, 16.10182093, 74.36211347, 63.29741618,
32.41800177, 92.23765324, 23.72264387, 82.39455709,
75.06071403, 11.37844527};
py::list colors = py::cast(colors_);
for (int i = 0; i < N; ++i) {
auto poly__ = xt::random::rand<double>({N, 2});
vector<vector<double>> poly_(N);
// to vector<vector>>
for (int j = 0; j < N; ++j) {
poly_[j].resize(2);
poly_[j][0] = poly__(j, 0);
poly_[j][1] = poly__(j, 1);
}
// to numpy array
auto poly = py::array(py::cast(std::move(poly_)));
auto polygon = Polygon(Args(poly, true));
patches.append(polygon.unwrap());
}
auto colors__ = 100.0 * xt::random::rand<double>({patches.size()});
vector<double> colors_(colors__.begin(), colors__.end());
py::array colors = py::cast(colors_);
auto p = collections::PatchCollection(Args(patches), Kwargs("alpha"_a = 0.4));
p.set_array(Args(colors));
// NOTE: error in python3.6.9 ?
ax.add_collection(Args(p.unwrap()));
fig.colorbar(Args(p.unwrap()), Kwargs("ax"_a = ax.unwrap()));
#if USE_GUI
plt.show();
#else
......
......
add_demo(align_labels_demo align_labels_demo.cpp)
add_demo(gridspec_multicolumn gridspec_multicolumn.cpp)
add_demo(multiple_figs_demo multiple_figs_demo.cpp)
add_demo(colorbar_placement colorbar_placement.cpp)
add_demo(subplots subplots.cpp)
add_custom_target(subplots_axes_and_figures
DEPENDS align_labels_demo gridspec_multicolumn multiple_figs_demo
DEPENDS align_labels_demo gridspec_multicolumn multiple_figs_demo colorbar_placement
COMMAND align_labels_demo
COMMAND gridspec_multicolumn
COMMAND multiple_figs_demo
COMMAND colorbar_placement
COMMENT "subplots_axes_and_figures"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
// example from
// https://matplotlib.org/stable/gallery/subplots_axes_and_figures/colorbar_placement.html
#include <pybind11/embed.h>
#include <pybind11/stl.h>
#include <matplotlibcpp17/pyplot.h>
#include <xtensor/xrandom.hpp>
#include <vector>
namespace py = pybind11;
using namespace py::literals;
using namespace std;
using namespace matplotlibcpp17;
int main1() {
auto plt = matplotlibcpp17::pyplot::import();
auto [fig, axs] = plt.subplots(2, 2);
const vector<string> cmaps = {"RdBu_r", "viridis"};
for (auto col : {0, 1}) {
for (auto row : {0, 1}) {
auto x_ = xt::random::randn<double>({20, 20}) * (col + 1.0);
vector<vector<double>> x(20);
for (int i = 0; i < 20; ++i) {
x[i].resize(20);
for (int j = 0; j < 20; ++j)
x[i][j] = x_(i, j);
}
auto &ax = axs[col + row * 2];
auto pcm = ax.pcolormesh(Args(x), Kwargs("cmap"_a = cmaps[col]));
fig.colorbar(Args(pcm.unwrap()),
Kwargs("ax"_a = ax.unwrap(), "shrink"_a = 0.6));
}
}
#if USE_GUI
plt.show();
#else
plt.savefig(Args("colorbar_placement1.png"));
#endif
return 0;
}
int main() {
py::scoped_interpreter guard{};
main1();
}
#include <pybind11/embed.h>
#include <pybind11/stl.h>
#include <matplotlibcpp17/pyplot.h>
namespace py = pybind11;
using namespace py::literals;
using namespace std;
using namespace matplotlibcpp17;
int main() {
py::scoped_interpreter guard{};
auto plt = matplotlibcpp17::pyplot::import();
{
auto [fig, axs] = plt.subplots(3, 1);
std::cout << axs.size() << std::endl;
}
{
auto [fig, axs] = plt.subplots(1, 1);
std::cout << axs.size() << std::endl;
}
{
auto [fig, axs] = plt.subplots(3, 3);
std::cout << axs.size() << std::endl;
}
return 0;
}
......@@ -123,6 +123,11 @@ public:
legend::Legend legend(const pybind11::tuple &args = pybind11::tuple(),
const pybind11::dict &kwargs = pybind11::dict());
// pcolormesh
collections::QuadMesh
pcolormesh(const pybind11::tuple &args = pybind11::tuple(),
const pybind11::dict &kwargs = pybind11::dict());
// plot
pybind11::object plot(const pybind11::tuple &args = pybind11::tuple(),
const pybind11::dict &kwargs = pybind11::dict());
......@@ -230,6 +235,7 @@ private:
LOAD_FUNC_ATTR(hist2d, self);
LOAD_FUNC_ATTR(invert_yaxis, self);
LOAD_FUNC_ATTR(legend, self);
LOAD_FUNC_ATTR(pcolormesh, self);
LOAD_FUNC_ATTR(plot, self);
// NOTE: only when called with projection='3d', `plot_surface`, `plot_wireframe`, `set_zlabel` prop exists.
try {
......@@ -278,6 +284,7 @@ private:
pybind11::object hist2d_attr;
pybind11::object invert_yaxis_attr;
pybind11::object legend_attr;
pybind11::object pcolormesh_attr;
pybind11::object plot_attr;
pybind11::object plot_surface_attr;
pybind11::object plot_wireframe_attr;
......@@ -478,6 +485,13 @@ legend::Legend Axes::legend(const pybind11::tuple &args,
return legend::Legend(obj);
}
// pcolormesh
collections::QuadMesh Axes::pcolormesh(const pybind11::tuple &args,
const pybind11::dict &kwargs) {
pybind11::object ret = pcolormesh_attr(*args, **kwargs);
return collections::QuadMesh(ret);
}
// plot
pybind11::object Axes::plot(const pybind11::tuple &args,
const pybind11::dict &kwargs) {
......
......
......@@ -73,6 +73,15 @@ pybind11::object PatchCollection::set_array(const pybind11::tuple &args,
pybind11::object ret = set_array_attr(*args, **kwargs);
return ret;
}
/**
* @brief A wrapper class for matplotlib.collections.QuadMesh
**/
struct DECL_STRUCT_ATTR QuadMesh : public BaseWrapper {
public:
QuadMesh(pybind11::object quadmesh) { self = quadmesh; }
};
} // namespace matplotlibcpp17::collections
#endif /* MATPLOTLIBCPP17_COLLECTIONS_H */
......@@ -74,6 +74,22 @@ private:
pybind11::object wedge_attr;
};
/**
* @brief A wrapper class for matplotlib.patches.Polygon
**/
struct DECL_STRUCT_ATTR Polygon : public BaseWrapper {
public:
Polygon(const pybind11::tuple &args = pybind11::tuple(),
const pybind11::dict &kwargs = pybind11::dict()) {
polygon_attr =
pybind11::module::import("matplotlib.patches").attr("Polygon");
self = polygon_attr(*args, **kwargs);
}
private:
pybind11::object polygon_attr;
};
} // namespace matplotlibcpp17::patches
#endif /* MATPLOTLIBCPP17_PATCHES_H */
......@@ -300,18 +300,29 @@ PyPlot::subplots(const pybind11::dict &kwargs) {
std::tuple<figure::Figure, std::vector<axes::Axes>>
PyPlot::subplots(int r, int c, const pybind11::dict &kwargs) {
// subplots() returns [][] (if r > 1 && c > 1) else []
// return []axes in row-major
// NOTE: equal to Axes.flat
pybind11::tuple args = pybind11::make_tuple(r, c);
pybind11::list ret = subplots_attr(*args, **kwargs);
std::vector<axes::Axes> axes;
pybind11::object fig = ret[0];
figure::Figure figure(fig);
if (r == 1 and c == 1) {
pybind11::object ax = ret[1];
axes.push_back(axes::Axes(ax));
// python returns Axes
axes.push_back(axes::Axes(ret[1]));
} else if (r == 1 or c == 1) {
// python returns []Axes
pybind11::list axs = ret[1];
for (int i = 0; i < r * c; ++i)
axes.push_back(axes::Axes(axs[i]));
} else {
// python returns [][]Axes
pybind11::list axs = ret[1];
for (pybind11::size_t i = 0; i < axs.size(); ++i) {
axes.push_back(axes::Axes(axs[i]));
pybind11::list axsi = axs[i];
for (unsigned j = 0; j < axsi.size(); ++j)
axes.push_back(axes::Axes(axsi[j]));
}
}
return {figure, axes};
......
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment