Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ A few features of this library are the following:
* [Similar libraries](#similar-libraries)
* [Changelog](#changelog)
* [HEAD](#head)
* [v0.10.0](#v0100)
* [v0.9.1](#v091)
* [v0.9.0](#v090)
* [v0.8.0](#v080)
* [v0.7.0](#v070)
* [v0.5.1](#v051)
* [v0.5.0](#v050)
* [v0.4.0](#v040)
Expand Down Expand Up @@ -542,56 +547,60 @@ There are several other libraries like gplot++ around. These are the ones I refe

### HEAD

### 0.9.1
### v0.10.0 {#v0100}

- Use `[[nodiscard]]` where appropriate (see PR [#16](https://github.com/ziotom78/gplotpp/pull/16))

### v0.9.1 {#v091}

- Bug fixes in method `histogram` (see PR [#15](https://github.com/ziotom78/gplotpp/pull/15))

### 0.9.0
### v0.9.0 {#v090}

- New method `redirect_to_animated_gif`

### v0.8.0
### v0.8.0 {#v080}

- New methods `add_point_xerr`, `add_point_yerr`, and `add_point_xyerr`, and new overloads for functions `plot_xerr`, `plot_yerr`, `plot_xyerr`

### v0.7.0
### v0.7.0 {#v070}

- Add `Gnuplot::add_point`, `Gnuplot::get_num_of_points()`, `Gnuplot::get_points_x()`, and `Gnuplot::get_points_y()`, as well as a new overloaded method `Gnuplot::plot()` which does not require the vectors of `x` and `y`.

### v0.5.1 (a.k.a. 0.6.0)
### v0.5.1 (a.k.a. 0.6.0) {#v051}

- Add `Gnuplot::set_title`

### v0.5.0
### v0.5.0 {#v050}

- Add `redirect_to_dumb` and the `TerminalType` enum class to support the `dumb` terminal

- Use a smarter algorithm to specify ranges in `Gnuplot.set_xrange` and `Gnuplot.set_yrange`: now specifying one of the two extrema as `NAN` does not override the specification of the other.

### v0.4.0
### v0.4.0 {#v040}

- `Gnuplot::redirect_to_svg` has been added

- `Gnuplot::plot_vectors`, `Gnuplot::plot_vectors3d` have been added

### v0.3.1
### v0.3.1 {#v031}

- `Gnuplot::plot_xerr`, `Gnuplot::plot_yerr`, and `Gnuplot::plot_xyerr` have been added

### v0.3.0
### v0.3.0 {v030}

- The library is now supported under Windows

### v0.2.1
### v0.2.1 {#v021}

- Ensure that commands sent to Gnuplot are executed immediately ([#1](https://github.com/ziotom78/gplotpp/pull/1))

### v0.2.0
### v0.2.0 {#v020}

- New constants `GNUPLOTPP_VERSION`, `GNUPLOTPP_MAJOR_VERSION`, `GNUPLOTPP_MINOR_VERSION`, and `GNUPLOTPP_PATCH_VERSION`

- 3D plots (after a suggestion by William Luciani)

### v0.1.0
### v0.1.0 {#v010}

- First release
175 changes: 96 additions & 79 deletions gplot++.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
*
* Version history
*
* - 0.10.0 (2025/09/23): use [[nodiscard]] where appropriate
*
* - 0.9.1 (2025/02/06): bug fixes in method `histogram`
*
* - 0.9.0 (2024/11/19): new method `redirect_to_animated_gif`
Expand Down Expand Up @@ -74,7 +76,7 @@
#include <unistd.h>
#endif

const unsigned GNUPLOTPP_VERSION = 0x000901;
const unsigned GNUPLOTPP_VERSION = 0x000a00;
const unsigned GNUPLOTPP_MAJOR_VERSION = (GNUPLOTPP_VERSION & 0xFF0000) >> 16;
const unsigned GNUPLOTPP_MINOR_VERSION = (GNUPLOTPP_VERSION & 0x00FF00) >> 8;
const unsigned GNUPLOTPP_PATCH_VERSION = (GNUPLOTPP_VERSION & 0xFF);
Expand Down Expand Up @@ -131,12 +133,12 @@ class Gnuplot {
std::vector<double> list_of_yerr;

void check_consistency() const {
assert(list_of_x.size() == list_of_y.size());
assert(list_of_x.size() == list_of_y.size());

if(list_of_xerr.size() > 0)
assert(list_of_xerr.size() == list_of_x.size());
if(list_of_yerr.size() > 0)
assert(list_of_yerr.size() == list_of_y.size());
if (list_of_xerr.size() > 0)
assert(list_of_xerr.size() == list_of_x.size());
if (list_of_yerr.size() > 0)
assert(list_of_yerr.size() == list_of_y.size());
}

public:
Expand All @@ -161,10 +163,10 @@ class Gnuplot {
};

enum class TerminalMode {
MONO,
ANSI,
ANSI256,
ANSIRGB,
MONO,
ANSI,
ANSI256,
ANSIRGB,
};

Gnuplot(const char *executable_name = "gnuplot", bool persist = true)
Expand Down Expand Up @@ -223,7 +225,7 @@ class Gnuplot {
return sendcommand(stream.str());
}

bool ok() { return connection != nullptr; }
[[nodiscard]] bool ok() { return connection != nullptr; }

/* Save the plot to a PNG file instead of displaying a window */
bool redirect_to_png(const std::string &filename,
Expand Down Expand Up @@ -265,50 +267,58 @@ class Gnuplot {
* `Gnuplot::show()` exactly N times.
*/
bool redirect_to_animated_gif(const std::string &filename,
const std::string &size = "800,600",
int delay_ms = 50,
bool loop = true) {
std::stringstream os;
const std::string &size = "800,600",
int delay_ms = 50, bool loop = true) {
std::stringstream os;

// Unfortunately, Gnuplot requires the delay to be expressed in units of 1/100 s
// instead of the more common unit 1/1000 s, so we need to divide by 10.
// We do not support a fixed number of repetitions: either you loop infinitely
// or play the animation just once
os << "set terminal gif animate delay " << delay_ms / 10 << " loop " << (loop ? 0 : 1) << "\n"
<< "set output '" << filename << "'\n";
return sendcommand(os);
// Unfortunately, Gnuplot requires the delay to be expressed in units of
// 1/100 s instead of the more common unit 1/1000 s, so we need to divide
// by 10. We do not support a fixed number of repetitions: either you loop
// infinitely or play the animation just once
os << "set terminal gif animate delay " << delay_ms / 10 << " loop "
<< (loop ? 0 : 1) << "\n"
<< "set output '" << filename << "'\n";
return sendcommand(os);
}

/* Send the plot to the terminal or to a text file */
bool redirect_to_dumb(const std::string &filename = "",
unsigned int width = 80,
unsigned int height = 50,
TerminalMode mode = TerminalMode::MONO) {
unsigned int width = 80, unsigned int height = 50,
TerminalMode mode = TerminalMode::MONO) {
std::stringstream os;

os << "set terminal dumb size " << width << " " << height;

switch(mode) {
case TerminalMode::MONO: os << "mono"; break;
case TerminalMode::ANSI: os << "ansi"; break;
case TerminalMode::ANSI256: os << "ansi256"; break;
case TerminalMode::ANSIRGB: os << "ansirgb"; break;
default: os << "mono";
}
os << "set terminal dumb size " << width << " " << height;

switch (mode) {
case TerminalMode::MONO:
os << "mono";
break;
case TerminalMode::ANSI:
os << "ansi";
break;
case TerminalMode::ANSI256:
os << "ansi256";
break;
case TerminalMode::ANSIRGB:
os << "ansirgb";
break;
default:
os << "mono";
}

os << "\n";
os << "\n";

if (! filename.empty()) {
os << "set output '" << filename << "'\n";
}
if (!filename.empty()) {
os << "set output '" << filename << "'\n";
}

return sendcommand(os);
}

bool set_title(const std::string &title) {
std::stringstream os;
os << "set title '" << escape_quotes(title) << "'";
return sendcommand(os);
std::stringstream os;
os << "set title '" << escape_quotes(title) << "'";
return sendcommand(os);
}

/* Set the label on the X axis */
Expand Down Expand Up @@ -435,59 +445,66 @@ class Gnuplot {
}
/* Add a point to the list of samples to be plotted */
void add_point(double x, double y) {
check_consistency();
check_consistency();

list_of_x.push_back(x);
list_of_y.push_back(y);
list_of_x.push_back(x);
list_of_y.push_back(y);
}

/* Add a value to the list of samples to be plotted */
void add_point(double y) {
add_point(static_cast<double>(list_of_x.size()), y);
add_point(static_cast<double>(list_of_x.size()), y);
}

/* Return the number of points added by `add_point` */
int get_num_of_points() const {
check_consistency();
[[nodiscard]] int get_num_of_points() const {
check_consistency();

return (int) list_of_x.size();
return (int)list_of_x.size();
}

/* Return the list of abscissas for the points added by `add_point` */
const std::vector<double> & get_points_x() const { return list_of_x; }
[[nodiscard]] const std::vector<double> &get_points_x() const {
return list_of_x;
}

/* Return the list of ordinates for the points added by `add_point` */
const std::vector<double> & get_points_y() const { return list_of_y; }
/* Return the list of ordinates for the points added by `add_point` */
[[nodiscard]] const std::vector<double> &get_points_y() const {
return list_of_y;
}

/* Create a plot using the values set with the method `add_point` */
void plot(const std::string &label = "", LineStyle style = LineStyle::LINES) {
check_consistency();
check_consistency();

_plot(label, style, false, list_of_x, list_of_y);
_plot(label, style, false, list_of_x, list_of_y);
}

/* Create a plot with X error bars using the values set with the method `add_point` */
/* Create a plot with X error bars using the values set with the method
* `add_point` */
void plot_xerr(const std::string &label = "") {
check_consistency();

plot_xerr(list_of_x, list_of_y, list_of_xerr, label);
}

/* Create a plot with X error bars using the values set with the method `add_point` */
/* Create a plot with X error bars using the values set with the method
* `add_point` */
void plot_yerr(const std::string &label = "") {
check_consistency();

plot_yerr(list_of_x, list_of_y, list_of_yerr, label);
}

/* Create a plot with X error bars using the values set with the method `add_point` */
/* Create a plot with X error bars using the values set with the method
* `add_point` */
void plot_xyerr(const std::string &label = "") {
check_consistency();

plot_xyerr(list_of_x, list_of_y, list_of_xerr, list_of_yerr, label);
}

template <typename T>
template <typename T>
void histogram(const std::vector<T> &values, size_t nbins,
const std::string &label = "",
LineStyle style = LineStyle::BOXES) {
Expand All @@ -506,28 +523,28 @@ class Gnuplot {

std::vector<size_t> bins{};

// Check if all the elements are the same
if (min_iter != max_iter) {
min = *min_iter;
max = *max_iter;
binwidth = (max - min) / nbins;

bins.resize(nbins);
for (const auto &val : values) {
int index = static_cast<int>((val - min) / binwidth);
if (index >= int(nbins))
--index;

bins.at(index)++;
}
} else {
// Just one bin…

min = max = *min_iter;
binwidth = 1.0;
nbins = 1;
bins.push_back(static_cast<double>(values.size()));
}
// Check if all the elements are the same
if (min_iter != max_iter) {
min = *min_iter;
max = *max_iter;
binwidth = (max - min) / nbins;

bins.resize(nbins);
for (const auto &val : values) {
int index = static_cast<int>((val - min) / binwidth);
if (index >= int(nbins))
--index;

bins.at(index)++;
}
} else {
// Just one bin…

min = max = *min_iter;
binwidth = 1.0;
nbins = 1;
bins.push_back(static_cast<double>(values.size()));
}

std::stringstream of;
for (size_t i{}; i < nbins; ++i) {
Expand Down
Loading