Skip to content
Snippets Groups Projects
Select Git revision
  • 6eb8b6aea1d35a723f96df074980bea867b2fabb
  • master default protected
  • Restore
  • VisualisationUpgrade
4 results

matplotlibcpp17

  • Open with
  • Download source code
  • Your workspaces

      A workspace is a virtual sandbox environment for your code in GitLab.

      No agents available to create workspaces. Please consult Workspaces documentation for troubleshooting.

  • matplotlibcpp17

    A C++ header-only library for matplotlib based on pybind


    matplotlibcpp17 is an yet another C++ library for matplotlib featuring more functionalities than matplotlibcpp.

    It is supposed to provide the user with almost full access to matplotlib features in C++, by implementing as many wrapper classes of matplotlib module as possible (like axes::Axes, figure::Figure). And its primary advantage over conventional matplotlibcpp is that the user can pass a variety of arguments as in the form of args and kwargs thanks to pybind11, without the need for coversion to map<string, string>, thus leading to more flexibility.

    Dependencies

    • pybind11 >= 2.4.3
      • sudo apt install pybind11-dev (on Ubuntu20.04)
      • or manual install
    • matplotlib >= 3.4.0
    • numpy for mplot3d
    • (xtensor == 0.24.0 + xtl, only for gallery demos)

    Usage

    Installation

    $ mdkir build; cd build;
    $ cmake .. -DADD_DEMO=0 (-DCMAKE_INSTALL_PREFIX=<custom path>)
    $ make -j
    $ make install
    $ (make uninstall)

    For using matplotlibcpp17 from CMakeLists.txt, see hello_world example.

    find_package(matplotlibcpp17)
    ...
    target_link_libraries(a.out matplotlibcpp17::matplotlibcpp17)

    Use by add_subdirectory

    add_subdirectory(path to matplotlibcpp17)
    ...
    target_link_libraries(a.out matplotlibcpp17::matplotlibcpp17)

    Include matplotlibcpp17 directly

    descibed in minimal example.

    Syntax

    The user will need to capsulate arguments in Args(arg1, arg2, ...) == pybind11:tuple and keyword arguments in Kwargs("k1"_a = v1, "k2"_a = v2, ...) == pybind11::dict. The returned value is a wrapper class for pybind. Please refer to the reference and examples below.

    • exception: subplots, TBDs
    • conversion: Wrapper class of matplotlibcpp17 like ::container::BarContainer needs to be passed to python interpreter using unwrap() method in args and kwargs.

    Examples

    minimal example

    g++ ./hello_world/hello_world.cpp -std=c++17 -I./include -I/usr/include/python3.x -I<path to pybind11> -lpython3.x
    ./a.out

    gives

    minimal example

    subplots

    From gallery/subplots_axes_and_figures/align_labels_demo.cpp.

      auto plt = matplotlibcpp17::pyplot::import();
    
      // corresponding wrapper class for returned value is implemented in this library
      /// gs is of type gridspec::GridSpec
      auto gs = GridSpec(2, 2);
    
      /// pass wrapper class object like gs[0, :] of ::gridspec::SubplotSpec to the interpreter using .unwrap() method as python object
      auto ax = fig.add_subplot(Args(gs(0, py::slice(0, 2, 1)).unwrap()));
    
      ax.plot(Args(arange(0, 1000000, 10000)));
      ax.set_ylabel(Args("YLabel0"));
      ax.set_xlabel(Args("XLabel0"));

    subplots_axes_and_figures

    bar plot

    From gallery/lines_bars_and_markers/bar_label_demo.cpp. Here subplots() returns tuple<Figure, Axes>.

      auto [fig, ax] = plt.subplots();
      auto p1 = ax.bar(Args(ind, menMeans, width),
                       Kwargs("yerr"_a = menStd, "label"_a = "Men"));
      auto p2 = ax.bar(
          Args(ind, womenMeans, width),
          Kwargs("bottom"_a = menMeans, "yerr"_a = womenStd, "label"_a = "Women"));
      ax.axhline(Args(0), Kwargs("color"_a = "grey", "linewidth"_a = 0.8));
      ax.set_ylabel(Args("Scores"));
      ax.set_title(Args("Scores by group and gender"));
    
      ax.set_xticks(Args(ind, py::make_tuple("G1", "G2", "G3", "G4", "G5")));
      ax.legend();
    
      // pass wrapper class object like p1 of ::container::BarContainer to the interpreter using .unwrap() method as python object
      ax.bar_label(Args(p1.unwrap()), Kwargs("label_type"_a = "center"));
      ax.bar_label(Args(p2.unwrap()), Kwargs("label_type"_a = "center"));
      ax.bar_label(Args(p2.unwrap()));
      plt.show();

    bar_label_demo1

    image

    2D-style pybind11 array can be plotted as an image using imshow() function.

    From images_contours_and_fields/image_demo

      vector<vector<double>> Z2D{...};
      auto Zpy = py::array(py::cast(std::move(Z2D)));
      ax.imshow(Args(Zpy), Kwargs("interpolation"_a = "bilinear",
                                  "cmap"_a = "RdYlGn", "origin"_a = "lower",
                                  "extent"_a = py::make_tuple(-3, 3, -3, 3),
                                  "vmax"_a = vmax, "vmin"_a = vmin));

    image_demo

    fill

    Fucntions like subplots, TBDs are overloaded because they return different types depending on the arguments. Here subplots() returns tuple<Figure, vector<Axes>>.

    From gallery/lines_bars_and_markers

      auto [fig, axes] =
          plt.subplots(1, 3,
                       Kwargs("figsize"_a = py::make_tuple(9, 3),
                               "subplot_kw"_a = py::dict("aspect"_a = "equal")));
      auto ax1 = axes[0], ax2 = axes[1], ax3 = axes[2];

    fill

    quiver

    Use .unwrap() method to pass wrapper class of matplotlibcpp17 to plotting functions.

    From gallery/images_contours_and_fields/quiver_demo.cpp

      auto plt = matplotlibcpp17::pyplot::import();
      auto [fig1, ax1] = plt.subplots();
      ax1.set_title(Args("Arrows scale with plot width, not view"));
      auto Q = ax1.quiver(Args(X, Y, U, V, M),
                          Kwargs("units"_a = "x", "pivot"_a = "tip",
                                  "width"_a = 0.022, "scale"_a = 1.0 / 0.15));
      auto qk =
          ax1.quiverkey(Args(Q.unwrap(), 0.9, 0.9, 1, R"($1 \frac{m}{s}$)"),
                        Kwargs("labelpos"_a = "E", "coordinates"_a = "figure"));
      ax1.scatter(Args(X, Y), Kwargs("color"_a = "0.5", "s"_a = 1));

    quiver_demo3

    3D

    To plot 3D graph with projection = "3d", following code is required.

    #include <matplotlibcpp17/mplot3d.h>
    
    matplotlibcpp17::mplot3d::import();

    gif

    Currently only ArtistAnimation is supported. FuncAnimation interface maybe implemented in the future.

    From gallery/artist_animation/random_walk.cpp

    random_walk

    Demos

    gallery folder contains corresponding examples from the official website of matplotlib with the same structure.

    build

    If you want to build the demos, use -DADD_DEMO=1 (by default it is 0).

    $ mkdir build; cd build
    $ cmake .. -DADD_DEMO={0, 1} -DUSE_GUI={0, 1}
    $ make -j

    If you do not need to see the demo with plt.show(), use -DUSE_GUI=1 (by default it is 0). Otherwise the executables will plt.savefig() to gallery/images directory.

    make <gallery directory name> runs all the executables under that directory.

    make lines_bars_and_markers

    Contributing

    Contributions to this project are welcome if you could add or want/need more modules :)