A header-only C++ interface to Gnuplot. See this video for a demo (running Visual Studio under Windows 10).
This repository contains the file gplot++.h, which provides a way for C++ programs to connect to a Gnuplot instance to produce plots. To use this library, you must first install Gnuplot on your system!
A few features of this library are the following:
- Header-only library: very easy to install
- Plot
std::vectorvariables - Multiple series in the same plot
- Multiple plots (via
Gnuplot::multiplot) - Logarithmic axes (via
Gnuplot::set_logscale) - Histograms (via
Gnuplot::histogram) - Custom ranges (via
Gnuplot::set_xrangeandGnuplot::set_yrange) - Possibility to save the plots in PNG and PDF files
- 3D plots (new in 0.2.0)
- gplot++
- Table of Contents
Of course, before using gplot++.h you must have Gnuplot installed and available in the PATH! We provide here instructions about how to install Gnuplot under Windows, Mac OS X, and Linux.
Windows users, beware that the standard installation won't work with gplot++.h because you need to activate a flag during the installation!
Download the Gnuplot installer from the SourceForge website. Be sure not to download the .tar.gz file; instead, you should download the file ending with .exe, e.g., gp542-win64-mingw.exe.
When you run the installer, pay attention to the option Add application directory to your PATH environment variable while installing Gnuplot, otherwise gplot++.h will fail to generate the plots! See this video for help.
Linux users should use their package manager to install Gnuplot:
# Debian, Ubuntu, Linux Mint
sudo apt-get install gnuplot
# Arch, Manjaro
sudo pacman -Syu gnuplot
# Fedora
sudo dns install gnuplot
The preferred way to install Gnuplot is using Homebrew from the terminal:
brew install gnuplot
Once you have Gnuplot installed, download the file gplot++.h and save it in the same folder as your program. That's all.
This video shows how to include gplot++.h in a C++ project created using Visual Studio 2019 (Windows).
Here is the output of one of the examples:
The source code of the example is in file example-complex.cpp:
#include "gplot++.h"
int main(void) {
Gnuplot plt{};
std::vector<double> x{1, 2, 3, 4, 5}, y{5, 2, 4, 1, 3};
// Save the plot into a PNG file with the desired size (in pixels)
plt.redirect_to_png("complex.png", "800,600");
/* Create two plots with the following layout (2 rows, 1 column):
*
* +------------------------+
* | |
* | Plot #1 |
* | |
* +------------------------+
* | |
* | Plot #2 |
* | |
* +------------------------+
*/
plt.multiplot(2, 1, "Title");
// Plot #1
plt.set_title("Plot #1");
plt.set_xlabel("X axis");
plt.set_ylabel("Y axis");
plt.plot(x, y, "x-y plot");
plt.plot(y, x, "y-x plot", Gnuplot::LineStyle::LINESPOINTS);
plt.show(); // Always call "show"!
// Plot #2
plt.set_title("Plot #2");
plt.set_xlabel("Value");
plt.set_ylabel("Number of counts");
plt.histogram(y, 2, "Histogram");
plt.set_xrange(-1, 7);
plt.set_yrange(0, 5);
plt.show(); // Always call "show"!
}The only symbol exported by file gplot++.h is the Gnuplot class. When you instance an object of this class, it will silently start gnuplot in the background and open a pipe through it:
#include "gplot++.h"
int main() {
Gnuplot plt{};
// ...
}If Gnuplot is not available in your PATH (probably this is most common on Windows system), you can specify the full path to the executable:
#include "gplot++.h"
int main() {
Gnuplot plt{R"(C:\Program Files\Gnuplot\gnuplot.exe)"};
// ...
}The connection will be automatically closed once the variable plt goes out of scope; by default, the Gnuplot window will be left open. In this way, you can navigate through the Gnuplot window even after your C++ has completed its execution.
There are two ways to produce a plot; both require you to call the Gnuplot::plot method:
- Pass one
std::vectorvariable, which will be used to set theycoordinates of the points; - Pass two
std::vectorvariables; these will be used to set the(x, y)coordinates of the points.
You can call plot multiple times, and each time your call will be recorded in a list. When you are ready to produce a plot, call Gnuplot::show, like in the following example:
several ways to produce a plot. Each of them requires you to pass the data to plot through one or more std::vector variables:
std::vector<int> x{1, 2, 4}; // No problem to use a vector of ints
std::vector<double> y1{3.1, -4.6, 5.1};
std::vector<double> y2{1.3, 1.6, 4.1};
Gnuplot plt{};
// Just pass the set of y values
plt.plot(y1);
// You can provide a label and a linestyle
plt.plot(x, y2, "Dataset #1", Gnuplot::LineStyle::LINESPOINTS);
// Now produce the plot
plt.show();New in version 0.7.0: Instead of providing the two vectors, you can call Gnuplot::add_point() repeatedly and then call Gnuplot::plot() without specifying vectors. See the example program example-addpoint.cpp.
Gplot++ implements the method Gnuplot::histogram, which computes the histogram of a series and plot it using Gnuplot. Here is an example (example-histogram.cpp):
#include "gplot++.h"
int main(void) {
Gnuplot gnuplot{};
std::vector<double> y{5, 2, 4, 1, 3};
gnuplot.histogram(y, 2, "Histogram");
gnuplot.set_xlabel("Value");
gnuplot.set_ylabel("Number of counts");
gnuplot.set_xrange(1, 5);
gnuplot.set_yrange(0, 5);
gnuplot.show();
}The parameters to Gnuplot::histogram are the following:
-
A vector containing the values to use in the plot;
-
The number of bins to plot (two bins in the example above);
-
A label for the plot (optional, default is empty)
-
The line style (optional, default is
Gnuplot::LineStyle::BOXES)
There are several line styles:
-
Gnuplot::LineStyle::DOTS(only use this when you have many points); -
Gnuplot::LineStyle::LINES(the default); -
Gnuplot::LineStyle::POINTS; -
Gnuplot::LineStyle::LINESPOINTS; -
Gnuplot::LineStyle::STEPS; -
Gnuplot::LineStyle::BOXES(only used for histograms). -
Gnuplot::LineStyle::VECTORS(only used for 2D and 3D vector fields).
You can manually assign a range to the X and Y axes using the methods Gnuplot::set_xlabel and Gnuplot::set_ylabel:
Gnuplot plt{};
plt.set_xrange(1.5, 3.5);
plt.set_yrange(); // No parameters means automatic axesIf you are creating multiple plots (see below), you should probably reset the x and y ranges after each call to Gnuplot::show.
You can also provide a label for both axes:
plt.set_xlabel("Time [s]");
plt.set_ylabel("Speed [cm/s]");To set a logarithmic scale, use Gnuplot::set_logscale:
Gnuplot plt{};
plt.set_logscale(Gnuplot::AxisScale::LOGXY);Possible parameters are:
Gnuplot::AxisScale::LINEAR(the default);Gnuplot::AxisScale::LOGX;Gnuplot::AxisScale::LOGY;Gnuplot::AxisScale::LOGXY.
You can make several plots within the same window using the method Gnuplot::multiplot. It accepts the following parameters:
-
The number of rows to use;
-
The number of columns to use;
-
A title (optional, default is no title).
You must paint the several plot in order, and each time you complete one plot you must call Gnuplot::show.
Starting from version 0.3.1, gplot++.h supports plots with error bars through these functions:
Gnuplot::plot_xerr(x, y, xerr, label = "");
Gnuplot::plot_yerr(x, y, yerr, label = "");
Gnuplot::plot_xyerr(x, y, xerr, yerr, label = "");Here is an example (example-errorbars.cpp):
#include "gplot++.h"
int main(void) {
Gnuplot plt{};
std::vector<double> x{1, 2, 3, 4, 5}, y{5, 2, 4, 1, 3};
std::vector<double> xerr{0.2, 0.2, 0.1, 0.1, 0.2},
yerr{0.3, 0.4, 0.2, 0.6, 0.7};
/* Create four plots with the following layout (2 rows, 2 columns):
*
* +------------------------+------------------------+
* | | |
* | Plot #1 | Plot #2 |
* | | |
* +------------------------+------------------------+
* | | |
* | Plot #3 | Plot #4 |
* | | |
* +------------------------+------------------------+
*/
plt.multiplot(2, 2, "Title");
// Plot #1
plt.set_xlabel("X axis");
plt.set_ylabel("Y axis");
plt.plot(x, y, "", Gnuplot::LineStyle::POINTS);
plt.show(); // Always call "show"!
// Plot #2: X error bar
plt.set_xlabel("X axis");
plt.set_ylabel("Y axis");
plt.plot_xerr(x, y, xerr);
plt.show(); // Always call "show"!
// Plot #3: Y error bar
plt.set_xlabel("X axis");
plt.set_ylabel("Y axis");
plt.plot_yerr(x, y, yerr);
plt.show(); // Always call "show"!
// Plot #4: X and Y error bars
plt.set_xlabel("X axis");
plt.set_ylabel("Y axis");
plt.plot_xyerr(x, y, xerr, yerr);
plt.show(); // Always call "show"!
}You can create 3D plots using the command plot3d, which takes three vectors. See the file example-3d.cpp:
#include "gplot++.h"
#include <cmath>
#include <iostream>
int main(void) {
Gnuplot gnuplot{};
std::vector<double> x, y, z;
for (double angle = 0; angle < 6 * M_PI; angle += 0.1) {
x.push_back(cos(angle));
y.push_back(sin(angle));
z.push_back(angle / 2 * M_PI);
}
gnuplot.plot3d(x, y, z);
gnuplot.show();
}Here is the result:
Starting from version 0.4.0, gplot++ supports vector field plots, both in 2D and 3D, through the methods Gnuplot::plot_vectors and Gnuplot::plot_vectors3d:
#include "gplot++.h"
#include <cmath>
#include <vector>
using namespace std;
int main(void) {
Gnuplot gnuplot{};
vector<double> x{}, y{};
vector<double> vx{}, vy{};
// Sample a regular grid. Use a small tilt to avoid sampling
// the grid at the origin
for (double cur_x{-10.1}; cur_x <= 10; cur_x += 1) {
for (double cur_y{-10.1}; cur_y <= 10; cur_y += 1) {
x.push_back(cur_x);
y.push_back(cur_y);
double r{sqrt(pow(cur_x, 2) + pow(cur_y, 2))};
double cur_vx{-cur_x / r};
double cur_vy{-cur_y / r};
vx.push_back(cur_vx);
vy.push_back(cur_vy);
}
}
gnuplot.plot_vectors(x, y, vx, vy);
gnuplot.show();
}It is often useful to save the plot into a file, instead of opening a window. You can save plots in PNG format if you call the method Gnuplot::redirect_to_png:
Gnuplot plt{};
// Call this immediately after you constructed the object "plt"
plt.redirect_to_png("image.png", "800,600");The first parameter is the name of the image file to create, and the second is a string specifying the size of the image, in the format width,height (in pixels). If you avoid passing the second parameter, a sensible default will be used:
Gnuplot plt{};
// Use the default size
plt.redirect_to_png("image.png");You can save the plot in a PDF file, which should be the preferred format if you plan to include the plot in a LaTeX document:
Gnuplot plt{};
// Call this immediately after you constructed the object "plt"
plt.redirect_to_pdf("image.pdf", "20cm,15cm");Unlike Gnuplot::redirect_to_png, when you create a PDF file you can use several measure units to specify the size of the image. In this case too, you can avoid passing the second parameter, and a reasonable default will be used.
You can save the plot in a SVG file via the method Gnuplot::redirect_to_svg. In this case, the SVG file will be interactive when opened in a web browser.
Finally, you can use Gnuplot::redirect_to_dumb to send the plot to the terminal or to a text file. You can pass a Gnuplot::TerminalMode value to specify if you want to include ANSI escape codes to produce colors, as shown in example-dumb.cpp:
You can plot animations interactively by simply running a for loop and adding a delay before plotting the next frame. A better solution is to create an animated GIF file using Gnuplot::redirect_to_animated_gif:
int main(void) {
Gnuplot gnuplot{};
std::vector<double> x{1, 2, 3, 4, 5}, y{5, 2, 4, 1, 3};
std::cout << "Running gplot++ v" << GNUPLOTPP_MAJOR_VERSION << "."
<< GNUPLOTPP_MINOR_VERSION << "." << GNUPLOTPP_PATCH_VERSION
<< "\n";
gnuplot.redirect_to_animated_gif("animation.gif", "800,600", 1000, true);
for(int i{}; i < (int) x.size(); ++i) {
gnuplot.add_point(x[i], y[i]);
gnuplot.plot(); // Do the plot
// In an animation, it is advisable to force the x/y ranges in advance
gnuplot.set_xrange(0, 6);
gnuplot.set_yrange(0, 6);
gnuplot.show(); // Add the frame to the GIF file
}
gnuplot.show();
std::cout << "Press any key to quit...";
std::getchar();
}Here is the result:
You can pass commands to Gnuplot using the method Gnuplot::sendcommand:
Gnuplot plt{};
plt.sendcommand("set xlabel 'X axis'");
plt.sendcommand("plot sin(x)");There are several other libraries like gplot++ around. These are the ones I referenced while developing my own's:
- gnuplot-iostream: it has much more features than gplot++, but it is slightly more difficult to install and use.
- gnuplot-cpp: another header-only library. It lacks support for high-level stuff like
std::vectorplotting.
- Use
[[nodiscard]]where appropriate (see PR #16)
- Bug fixes in method
histogram(see PR #15)
- New method
redirect_to_animated_gif
- New methods
add_point_xerr,add_point_yerr, andadd_point_xyerr, and new overloads for functionsplot_xerr,plot_yerr,plot_xyerr
- Add
Gnuplot::add_point,Gnuplot::get_num_of_points(),Gnuplot::get_points_x(), andGnuplot::get_points_y(), as well as a new overloaded methodGnuplot::plot()which does not require the vectors ofxandy.
- Add
Gnuplot::set_title
-
Add
redirect_to_dumband theTerminalTypeenum class to support thedumbterminal -
Use a smarter algorithm to specify ranges in
Gnuplot.set_xrangeandGnuplot.set_yrange: now specifying one of the two extrema asNANdoes not override the specification of the other.
-
Gnuplot::redirect_to_svghas been added -
Gnuplot::plot_vectors,Gnuplot::plot_vectors3dhave been added
Gnuplot::plot_xerr,Gnuplot::plot_yerr, andGnuplot::plot_xyerrhave been added
- The library is now supported under Windows
- Ensure that commands sent to Gnuplot are executed immediately (#1)
-
New constants
GNUPLOTPP_VERSION,GNUPLOTPP_MAJOR_VERSION,GNUPLOTPP_MINOR_VERSION, andGNUPLOTPP_PATCH_VERSION -
3D plots (after a suggestion by William Luciani)
- First release







