I was looking for a light-weighted C++ library for visualization to integrate into my programs when I realized that there are no officialy small ones existing. One attempt that I noticed was a C++ wrapper for the famous visualization python library: Matplotlib (the original one can be found HERE; and the modified program with CMake build can be found HERE). However, looking at the source codes to find a way to expand the library, I found out that the current approach directly utilizing Python/C API; makes it quite difficult for an expansion. That is the start of this library, written with pybind11 in hope of providing a more convenient way to connect with Matplotlib library.
- OS: Ubuntu (tested on 16.04, 19.04)
- compiler: tested with gcc-6
- C++11 and above
- python2/3
- pybind11 : C++ library for seamless conversion between C++ and python
- matplotlib
- cmake: >= 3.8
cd /path/to/this/root/directory
mkdir build && cd build && cmake ../
make -j`nproc`
- BUILD_EXAMPLES=ON/OFF (default OFF): whether to build examples or not.
- WITH_DEBUG=ON/OFF (default OFF): whether to enable debug macro or not.
- WITH_TEST=ON/OFF (default OFF): whether to build test or not.
- WITH_DOC=ON/OFF (default ON): whether to build doxygen documentations or not.
All the examples can be found in examples directory.
Important parts of the code:
// import modules of matplotlib library
pe::vis::Matplotlib mpllib;
// check if the modules are imported successully or not
if (!mpllib.imported()) {
std::cout << "Failed to import matplotlib library\n";
exit(EXIT_FAILURE);
}
...
// create a figure of desired size
mpllib.figure(1200, 780);
// plot with default parameters
mpllib.plot(x, y);
// plot with user-input parameters
mpllib.plot(x, w,
{
{"color", pe::vis::Matplotlib::createAnyBaseMapData<std::string>("r")},
{"linestyle", pe::vis::Matplotlib::createAnyBaseMapData<std::string>("--")},
});
// plot with user-input parameters
mpllib.plot(x, z,
{
{"label", pe::vis::Matplotlib::createAnyBaseMapData<std::string>("log(x)")},
{"lw", pe::vis::Matplotlib::createAnyBaseMapData<int>(2)},
});
// limit for x axis
mpllib.xlim(0, 1000 * 1000);
// add grid
mpllib.grid();
// add title
mpllib.title("Sample plot");
// add legend with default location (best)
mpllib.legend();
// save figure
mpllib.savefig("Basic.png");
// show figure
mpllib.show();
It can be seen here that user can input flexible parameters of "arbitary" types (currently support bool, int, float, double, std::string - but the list of supported types can be easily extended) into the function; which make it easier to modify parameters just like in python code. To pass new parameters, you need to create a map like the following:
{
{"label", pe::vis::Matplotlib::createAnyBaseMapData<std::string>("log(x)")},
{"lw", pe::vis::Matplotlib::createAnyBaseMapData<int>(2)},
}
Each pair has the following structure:
{[string of name of the python parameter] : pe::vis::Matplotlib::createAnyBaseMapData<[type of the parameter]>([value of the parameter])}
More examples can be easily created by using current wrapped functions or adding more modules, functions from python side.