How to Use Python’s Matplotlib in C++?

2024-06-10C++,matplotlib,Python

Introduction

When processing data using C++, I often envy the ease with which Python’s rich libraries can be utilized. Among these, matplotlib stands out as particularly useful for its ability to effortlessly display various types of graphs.

In fact, even in C++, you can use a library called matplotlib-cpp to call Python’s matplotlib and directly display graphs.

This time, I have researched how to use this matplotlib-cpp. Here are my notes.

Installation

Download matplotlibcpp.h from matplotlib-cpp’s GitHub. Alternatively, you can clone the repository.

git clone https://github.com/lava/matplotlib-cpp.git

How to Use matplotlib-cpp

To use matplotlib-cpp, you need to have Python, matplotlib, and NumPy installed beforehand. Make sure to install these in advance.

The matplotlib-cpp itself is just a header file, so you can use it simply by including it in your C++ source code.

On Linux

Specify the path to the Python include files and libraries during the build. With GCC, it would be as follows:

% python3 --version
Python 3.11.4

% g++ sourcefile -std=c++11 -I/usr/include/python3.11 -l/usr/lib/python3.11

The paths to Python include files and libraries should match the installed version.

On Windows

There are some potential stumbling blocks on Windows, so caution is necessary.

Modifying the Source Code

The obtained matplotlibcpp.h cannot be used as it is. When attempting to compile, you should see a message stating that select_npy_type<long long> and select_npy_type<unsigned long long> are being redefined.

When reading the source code in matplotlib-cpp, you can see some comments near the definition of select_npy_type<long long> as follows.

// Sanity checks; comment them out or change the numpy type below if you're compiling on
// a platform where they don't apply

You should comment out the definition part as follows.

//template <> struct select_npy_type<long long> { const static NPY_TYPES type = NPY_INT64; };
//template <> struct select_npy_type<unsigned long long> { const static NPY_TYPES type = NPY_UINT64; };

This will eliminate the errors.

Build

In Windows, the following paths are required. Make sure to check these paths in advance.

  1. Python’s include file
  2. NumPy’s include file
  3. Python’s library

The default installation directory for Python is C:\Users\[User Name]\AppData\Local\Programs\Python on Windows. It’s too long. Therefore, it’s advisable to register it in the INCLUDE or LIB environment variables.

Additionally, building with GCC is not possible on Windows. You need to use MSVC (cl.exe) or Clang.

  • MSVC(cl.exe)

    cl /EHsc [source-files] /I \path\to\python\include /I \path\to\python\pkgs\[numpy-base-*****]\Lib\site-packages\numpy\core\include /link /LIBPATH \path\to\python\libs
  • Clang

    clang++ [source-files] -I\path\to\python\include -I\path\to\python\pkgs\[numpy-base-*****]\Lib\site-packages\numpy\core\include -l\path\to\python\libs\python311.lib

CMake

If you are using CMake, you can write the CMakeLists.txt as follows. This way is easier because it automatically searches for the paths of Python and NumPy, so if you have an environment where CMake is available, this is the recommended approach.

cmake_minimum_required(VERSION 3.14)
project([project-name] CXX)

add_executable([executable-file-name] [source-files])
target_compile_features([executable-file-name] PRIVATE cxx_std_11)

find_package(Python COMPONENTS Development NumPy REQUIRED)
target_include_directories([executable-file-name] PRIVATE ${Python_INCLUDE_DIRS} ${Python_NumPy_INCLUDE_DIRS})
target_link_libraries([executable-file-name] Python::Python Python::NumPy)

By using find_package(Python COMPONENTS Development NumPy), it automatically locates the paths for Python and NumPy. The last REQUIRED indicates that they are mandatory. For finding the Python path, CMake version 3.12 or later is required, and for finding the NumPy path, CMake version 3.14 or later is required.

For more details about find_package(Python), please refer to the official documentation of CMake.

If you are creating a Makefile, it generates the build by default in DEBUG mode, so (especially on Windows) you need to set the build type to Release.

cmake -DCMAKE_CXX_COMPILER=cl -DCMAKE_BUILD_TYPE=Release -G "MinGW Makefiles" ..

Example Code

You can use it in a similar way to Python’s matplotlib.

#define _USE_MATH_DEFINES
#include <cmath>
#include <map>
#include <string>
#include <vector>

#include "matplotlibcpp.h"

namespace plt = matplotlibcpp;

int main()
{
    size_t n = 100;
    double sigma = 0.5, mean = 5.0, tx;
    std::vector<double> x(n), y(n), z(n);
    std::map<std::string, std::string> style;

    for(int i = 0; i < n; i++){
        x[i] = i / 10.0;
        tx = x[i] - mean;
        y[i] = 10 / std::sqrt(2 * M_PI * sigma * sigma) * std::exp(-tx * tx / (2 * sigma * sigma));
        z[i] = std::sin(2 * M_PI * x[i]) - 2;
    }

    // Using initializer_list
    plt::plot({1, -1.3, 0.1, 0.5, -0.5, 0.8, -0.3, 1, 0, -1, 0.6});

    // Using lambda expression
    plt::plot(x, [](double t){
        return std::log(t) + 4;
    }, "b-");

    // Setting legends and lines (red dashed) with named_plot
    plt::named_plot("gaussian", x, y, "r--");

    style["label"] = "y = sin(2 * pi * x) - 2";
    style["color"] = "black";
    style["marker"] = "+";
    style["markeredgecolor"] = "green";
    style["linestyle"] = "-.";

    // Setting legends and line colors using map
    plt::plot(x, z, style);

    // Display range
    plt::xlim(0, 12);
    plt::ylim(-4, 10);

    // Axis label
    plt::xlabel("x");
    plt::ylabel("y");

    // Graph title
    plt::title("sample graph");

    // Legends
    plt::legend();

    plt::show();

    return 0;
}

Output

Figure 1

You can draw various other types of graphs as well. Examples of what kind of graphs you can draw can be found in the sample code on the GitHub repository.

Conclusion

Here, I have summarized how to use matplotlib-cpp, a library that allows you to use Python’s matplotlib in C++. While there are some points to be aware of when using it on Windows, it is a library worth trying out as it allows for easy graph plotting in a manner similar to the original matplotlib.

C++,matplotlib

Posted by izadori