Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
kyabe2718 committed Dec 26, 2019
0 parents commit 43d0068
Show file tree
Hide file tree
Showing 10 changed files with 1,772 additions and 0 deletions.
1,233 changes: 1,233 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.15)
project(matplotlibcpp)

set(CMAKE_CXX_STANDARD 17)

find_package(Boost COMPONENTS python3 numpy3)
find_package(Python3 COMPONENTS Interpreter Development NumPy)

add_library(matplotlibcpp INTERFACE)
target_include_directories(matplotlibcpp INTERFACE ${CMAKE_CURRENT_LIST_DIR}/inc)
target_link_libraries(matplotlibcpp INTERFACE Python3::Python Python3::NumPy Boost::python3 Boost::numpy3)


file(GLOB SRCS ${CMAKE_CURRENT_LIST_DIR}/test/*.cpp)
foreach(SRC ${SRCS})
get_filename_component(TARGET_NAME ${SRC} NAME_WE)
add_executable(${TARGET_NAME} ${SRC})
target_link_libraries(${TARGET_NAME} matplotlibcpp)
endforeach()

6 changes: 6 additions & 0 deletions inc/matplotlibcpp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

#include "matplotlibcpp/axes.hpp"
#include "matplotlibcpp/figure.hpp"
#include "matplotlibcpp/pyplot.hpp"
#include "matplotlibcpp/animation.hpp"
22 changes: 22 additions & 0 deletions inc/matplotlibcpp/animation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once

#include "util.hpp"

namespace matplotlibcpp::animation
{

struct FuncAnimation
{
template <class... TKWArgs>
FuncAnimation(const Figure& fig, void (*plotter)(py::object), const std::pair<const char*, TKWArgs>&... kwargs)
: self{
py::import("matplotlib.animation")
.attr("FuncAnimation")(
*py::make_tuple(fig.self, py::make_function(static_cast<void (*)(py::object)>(plotter))), **to_dict(kwargs...))}
{
}

py::object self;
};

} // namespace matplotlibcpp::animation
92 changes: 92 additions & 0 deletions inc/matplotlibcpp/axes.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#pragma once

#include "util.hpp"

namespace matplotlibcpp
{

struct Axes
{
explicit Axes(const py::object& self)
: self{self},
plot_{self.attr("plot")}, scatter_{self.attr("scatter")}, hist_{self.attr("hist")},
hlines_{self.attr("hlines")}, vlines_{self.attr("vlines")}, annotate_{self.attr("annotate")},
set_title_{self.attr("set_title")}, set_xlabel_{self.attr("set_xlabel")}, set_ylabel_{self.attr("set_ylabel")}
{
}

template <class T, class... TKWArgs>
void plot(const std::vector<T>& x, const std::vector<T>& y, const std::pair<const char*, TKWArgs>&... kwargs)
{
plot_(*py::make_tuple(to_ndarray(x), to_ndarray(y)), **to_dict(kwargs...));
}

template <class T, class... TKWArgs>
void plot(const std::vector<T>& x, const std::vector<T>& y, const char* fmt, const std::pair<const char*, TKWArgs>&... kwargs)
{
plot_(*py::make_tuple(to_ndarray(x), to_ndarray(y), fmt), **to_dict(kwargs...));
}

template <class T, class... TKWArgs>
void scatter(const std::vector<T>& x, const std::vector<T>& y, const std::pair<const char*, TKWArgs>&... kwargs)
{
scatter_(*py::make_tuple(to_ndarray(x), to_ndarray(y)), **to_dict(kwargs...));
}

template <class T, class... TKWArgs>
void hist(const std::vector<T>& x, const std::pair<const char*, TKWArgs>&... kwargs)
{
hist_(to_ndarray(x), **to_dict(kwargs...));
}

template <class... TKWArgs>
void hlines(double y, double xmin, double xmax, const std::pair<const char*, TKWArgs>&... kwargs)
{
hlines_(*py::make_tuple(y, xmin, xmax), **to_dict(kwargs...));
}

template <class... TKWArgs>
void vlines(double x, double ymin, double ymax, const std::pair<const char*, TKWArgs>&... kwargs)
{
vlines_(*py::make_tuple(self, x, ymin, ymax), **to_dict(kwargs...));
}

template <class... TKWArgs>
void arrow(double x0, double y0, double x1, double y1, const std::pair<const char*, TKWArgs>&... arrowprops)
{
annotate_(py::object(""),
**to_dict(std::make_pair("xy", py::make_tuple(x1, y1)), std::make_pair("xytext", py::make_tuple(x0, y0)),
std::make_pair("arrowprops", to_dict(arrowprops...))));
}

void arrow(double x0, double y0, double x1, double y1, const char* arrowstyle = "->")
{
annotate_(py::object(""),
**to_dict(std::make_pair("xy", py::make_tuple(x1, y1)), std::make_pair("xytext", py::make_tuple(x0, y0)),
std::make_pair("arrowprops",
to_dict(std::make_pair("arrowstyle", arrowstyle)))));
}

template <class... TKWArgs>
void set_title(const std::string& title, const std::pair<const char*, TKWArgs>&... kwargs)
{
set_title_(title.c_str(), **to_dict(kwargs...));
}

void set_xlabel(const std::string& label)
{
set_xlabel_(label.c_str());
}

void set_ylabel(const std::string& label)
{
set_ylabel_(label.c_str());
}

private:
using object = boost::python::object;
object self;
object plot_, scatter_, hist_, hlines_, vlines_, annotate_, set_title_, set_xlabel_, set_ylabel_;
};

} // namespace matplotlibcpp
45 changes: 45 additions & 0 deletions inc/matplotlibcpp/figure.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "util.hpp"
#include "axes.hpp"

namespace matplotlibcpp
{

struct Figure
{
using object = boost::python::object;

explicit Figure(const py::object& self)
: self{self},
add_axes_{self.attr("add_axes")},
add_subplot_{self.attr("add_subplot")},
legend{self.attr("legend")},
tight_layout{self.attr("tight_layout")},
clf{self.attr("clf")}
{
}

Axes add_axes(double l, double b, double w, double h)
{
auto axes = add_axes_(*py::make_tuple(l, b, w, h));
return Axes{axes};
}

Axes add_subplot(int nrows, int ncols, int index)
{
auto axes = add_subplot_(*py::make_tuple(nrows, ncols, index));
return Axes{axes};
}

object self;

// callable
object legend;
object tight_layout;
object clf;

private:
object add_axes_, add_subplot_;
};
} // namespace matplotlibcpp
147 changes: 147 additions & 0 deletions inc/matplotlibcpp/pyplot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#pragma once

#include "util.hpp"

namespace matplotlibcpp
{

struct pyplot
{
using object = boost::python::object;

template <class T = double, class... TKWArgs>
static void plot(const std::vector<T>& x, const std::vector<T>& y, const std::pair<const char*, TKWArgs>&... kwargs)
{
plot_(*py::make_tuple(to_ndarray(x), to_ndarray(y)), **to_dict(kwargs...));
}

template <class T = double, class... TKWArgs>
static void plot(const std::vector<T>& x, const std::vector<T>& y, const char* fmt, const std::pair<const char*, TKWArgs>&... kwargs)
{
plot_(*py::make_tuple(to_ndarray(x), to_ndarray(y), fmt), **to_dict(kwargs...));
}

template <class... TKWArgs>
static void arrow(double x0, double y0, double x1, double y1, const std::pair<const char*, TKWArgs>&... arrowprops)
{
annotate_(*py::make_tuple(py::object("")),
**to_dict(std::make_pair("xy", py::make_tuple(x1, y1)),
std::make_pair("xytext", py::make_tuple(x0, y0)),
std::make_pair("arrowprops", to_dict(arrowprops...))));
}

static void arrow(double x0, double y0, double x1, double y1, const char* arrowstyle = "->")
{
annotate_(*py::make_tuple(py::object("")),
**to_dict(std::make_pair("xy", py::make_tuple(x1, y1)),
std::make_pair("xytext", py::make_tuple(x0, y0)),
std::make_pair("arrowprops",
to_dict(std::make_pair("arrowstyle", arrowstyle)))));
}

template <class T, class... TKWArgs>
static void scatter(const std::vector<T>& x, const std::vector<T>& y, const std::pair<const char*, TKWArgs>&... kwargs)
{
scatter_(*py::make_tuple(to_ndarray(x), to_ndarray(y)), **to_dict(kwargs...));
}

template <class T, class... TKWArgs>
static void hist(const std::vector<T>& x, const std::pair<const char*, TKWArgs>&... kwargs)
{
hist_(*py::make_tuple(to_ndarray(x)), **to_dict(kwargs...));
}

template <class... TKWArgs>
static void title(const std::string& title, const std::pair<const char*, TKWArgs>&... kwargs)
{
title_(*py::make_tuple(title.c_str()), **to_dict(kwargs...));
}

static void xlim(double left, double right)
{
xlim_(left, right);
}

static void ylim(double bottom, double top)
{
ylim_(bottom, top);
}

static void xlabel(const std::string& label)
{
xlabel_(label.c_str());
}

static void ylabel(const std::string& label)
{
ylabel_(label.c_str());
}

template <class... TKWArgs>
static void hlines(double y, double xmin, double xmax, const std::pair<const char*, TKWArgs>&... kwargs)
{
hlines_(*py::make_tuple(y, xmin, xmax), **to_dict(kwargs...));
}

template <class... TKWArgs>
static void vlines(double x, double ymin, double ymax, const std::pair<const char*, TKWArgs>&... kwargs)
{
vlines_(*py::make_tuple(x, ymin, ymax), **to_dict(kwargs...));
}

template <class... TKWArgs>
static void subplot(int nrows, int ncols, int index, const std::pair<const char*, TKWArgs>&... kwargs)
{
subplot_(*py::make_tuple(nrows, ncols, index), **to_dict(kwargs...));
}

static void show() { show_(); }
static void legend() { legend_(); }
static void tight_layout() { tight_layout_(); }
static void savefig(const char* path) { savefig_(path); }
static void cla() { cla_(); }

static Figure figure()
{
return Figure{figure_()};
}

private:
inline static object plot_, scatter_, hist_, annotate_, title_;
inline static object xlim_, ylim_, xlabel_, ylabel_;
inline static object hlines_, vlines_;
inline static object subplot_, show_, legend_, tight_layout_;
inline static object figure_, savefig_, cla_;

public:
pyplot()
{
if (!Py_IsInitialized()) {
Py_Initialize();
np::initialize();
}
auto dict = py::dict{py::import("matplotlib.pyplot").attr("__dict__")};
plot_ = dict["plot"];
scatter_ = dict["scatter"];
hist_ = dict["hist"];
annotate_ = dict["annotate"];
title_ = dict["title"];
xlim_ = dict["xlim"];
ylim_ = dict["ylim"];
xlabel_ = dict["xlabel"];
ylabel_ = dict["ylabel"];
hlines_ = dict["hlines"];
vlines_ = dict["vlines"];
subplot_ = dict["subplot"];
show_ = dict["show"];
legend_ = dict["legend"];
tight_layout_ = dict["tight_layout"];
figure_ = dict["figure"];
savefig_ = dict["savefig"];
cla_ = dict["cla"];
}
};


inline auto plt = matplotlibcpp::pyplot{};
} // namespace matplotlibcpp
28 changes: 28 additions & 0 deletions inc/matplotlibcpp/util.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

#include <boost/python.hpp>
#include <boost/python/numpy.hpp>

namespace matplotlibcpp
{
namespace py = boost::python;
namespace np = boost::python::numpy;

template <class T, class = std::enable_if_t<std::is_arithmetic_v<typename T::value_type>>>
np::ndarray to_ndarray(const T& vec)
{
auto shape = py::make_tuple(vec.size());
auto dtype = np::dtype::get_builtin<typename T::value_type>();
auto strides = py::make_tuple(sizeof(typename T::value_type));
py::object owner;
return np::from_data(static_cast<const void*>(vec.data()), dtype, shape, strides, owner).copy();
}

template <class... TKWArgs>
py::dict to_dict(const std::pair<const char*, TKWArgs>&... kwargs)
{
py::dict ret;
((ret[kwargs.first] = kwargs.second), ...);
return ret;
}
} // namespace matplotlibcpp
15 changes: 15 additions & 0 deletions test/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <matplotlibcpp.hpp>

#include <boost/core/demangle.hpp>
#include <iostream>
#include <string>


int main()
{
using namespace Flier;
std::vector<double> x{1, 2, 3};
std::vector<double> y{1, 2, 3};
plt.scatter(x, y, std::make_pair("alpha", 0.5));
plt.show();
}
Loading

0 comments on commit 43d0068

Please sign in to comment.