GnuPlotScripting
A simple C++17 lib that helps you to quickly plot your data with GnuPlot
Install / Use
/learn @vincent-picaud/GnuPlotScriptingREADME
#+OPTIONS: H:3 toc:t \n:nil ::t |:t ^:{} -:t f:t *:t tex:t d:t tags:not-in-toc #+BLOG: wordpress #+POSTID: 931 #+DATE: [2019-12-06 Fri 19:40] #+TITLE: Easy Creation of GnuPlot Scripts from C++ #+TAGS: Cpp, GnuPlot
trick from https://github.com/rexim/org-cliplink/
[[https://travis-ci.org/vincent-picaud/GnuPlotScript][file:https://travis-ci.org/vincent-picaud/GnuPlotScripting.svg?branch=master]]
- Table of contents :TOC:noexport:
- [[#what-is-it][What is it?]]
- [[#news][News]]
- [[#contributors][Contributors]]
- [[#installation][Installation]]
- [[#examples][Examples]]
- [[#plot-and-fit-data][Plot and fit data]]
- [[#ascii-matrix-data][Ascii matrix data]]
- [[#new-matrix-data][(NEW) Matrix data]]
- [[#histogram][Histogram]]
- [[#graph][Graph]]
- [[#density-plot][Density plot]]
- [[#pipe-example][Pipe example]]
- [[#supported-export-formats][Supported export formats]]
- [[#global-config-demonstration][Global config demonstration]]
- [[#documentation][Documentation]]
- [[#data-classes][Data classes]]
- [[#script-classes][Script classes]]
- [[#global_config-class][Global_Config class]]
- [[#references][References]]
- [[#faq][FAQ]]
- What is it?
A simple C++17 library that allows easy creation and execution of gnuplot scripts. These scripts will embed their data and can be replayed/modified later.
The library depends on [[https://github.com/fmtlib/fmt][{fmt} library]].
I use it when I want to plot some data with a minimal effort when I develop stuff in C++.
For the moment the library is only tested under Linux (it should also works under Windows but I have not checked yet).
Feel free to use it: [[https://github.com/vincent-picaud/GnuPlotScripting][GitHub, GnuPlotScripting]].
** News
-
[2020-10-20 Tue] \
- Version v1.1.0!
- some compilation warning fixes
- a new Data_Array_2 class
-
[2020-01-18 Sat 09:17] \
- Version v1.0.0 release!
- More documentation
- Fix a bug in export_as(...,path/output_filename): the path was ignored
-
[2020-01-09 Thu 22:46] \
- Added =Data_Supervised= class and associated example (see Density plot in Example section)
- Code cleaning (no breaking change!)
- Tagged as v0.2.0 (v1.0.0 gets closer :-) )
-
[2019-12-09 Mon 18:34] \ Added SVG, TGIF, PNGCairo and PDFCairo export formats. Tagged as v0.0.3.
-
[2019-12-08 Sun 20:21] \ Some minor fixes + doc concerning Global_Config logger methods. Tagged as v0.0.2
-
[2019-12-08 Sun 11:21] \ Initial version. Tagged as v0.0.1
** Contributors
- [[https://github.com/Gjacquenot][Guillaume Jacquenot]]: Travis CI
- Installation
The library currently uses the [[https://mesonbuild.com/][meson]] build system.
If you are not familiar with meson, the compilation procedure is as follows:
#+BEGIN_SRC sh :eval never git clone https://github.com/vincent-picaud/GnuPlotScripting.git cd GnuPlotScripting/ meson build cd build ninja test #+END_SRC
Examples can then be found in the =build/examples/= directory.
If you want to install the package: #+BEGIN_SRC sh :eval never ninja install #+END_SRC
Note that you can define custom installation path, at the beginning of the compilation procedure, use:
#+BEGIN_SRC sh :eval never meson --prefix=/install_path/ build #+END_SRC
instead of =meson build=.
- Examples
** Plot and fit data
#+BEGIN_SRC sh :wrap "src cpp :eval never" :results output :exports results cat $(pwd)/examples/plot.cpp #+END_SRC
#+RESULTS: #+BEGIN_src cpp :eval never #include "GnuPlotScripting/GnuPlotScripting.hpp"
#include <iostream> #include <vector>
using namespace GnuPlotScripting;
// From: https://www.cs.hmc.edu/~vrable/gnuplot/using-gnuplot.html
int main() { std::vector<double> time, angle, stdvar;
time = {0.0, 1.0, 2.1, 3.1, 4.2, 5.2, 6.2, 7.2, 8.2, 9.1, 10.0, 11.0, 12.0, 12.9, 13.8, 14.9, 15.9, 17.0, 17.9, 18.9, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 32.9, 33.8, 34.7, 35.7, 36.6, 37.7};
angle = {-14.7, 8.6, 28.8, 46.7, 47.4, 36.5, 37.0, 5.1, -11.2, -22.4, -35.5, -33.6, -21.1, -15.0, -1.6, 19.5, 27.5, 32.6, 27.5, 20.2, 13.8, -1.3, -24.5, -25.0, -25.0, -20.2, -9.9, 5.8, 14.7, 21.8, 29.8, 21.4, 24.6, 25.8, 0.6, -16.6, -24.0, -24.6, -19.8};
stdvar = {3.6, 3.6, 3.0, 3.4, 3.5, 3.4, 10.3, 3.4, 3.4, 3.5, 3.6, 3.9, 3.9, 4.2, 2.7, 3.2, 2.8, 3.5, 2.7, 3.3, 3.4, 4.2, 6.7, 3.3, 3.1, 3.6, 3.2, 3.2, 3.0, 3.5, 2.7, 4.1, 2.7, 12.0, 2.9, 3.2, 3.7, 3.8, 3.5};
Script_File script("plot.gp");
Data_Vector data( time, angle, stdvar); // <- you can stack as many vector/valarray etc.. as you want // only size() and operator[] are required.
script.free_form("set title 'Cavendish Data'"); script.free_form("set xlabel 'Time (s)'"); script.free_form("set ylabel 'Angle (mrad)'"); script.free_form("set grid"); script.free_form("plot {} with yerrorbars notitle", data); script.free_form("replot {} u 1:2 with lines title '{}'", data, "raw data"); script.free_form("theta(t) = theta0 + a * exp(-t / tau) * sin(2 * pi * t / T + phi)"); script.free_form("fit theta(x) {} using 1:2:3 via a, tau, phi, T, theta0", data); script.free_form("replot theta(x) lw {} lc {} title 'best-fit curve'", 2, 4); script.export_as(PNG(), "plot"); } #+END_src
It generates this figure:
[[file:figures/plot.png]]
Note: the generated =plot.gp= gnutplot script embeds the data and you can replay it whenever you want: #+BEGIN_SRC sh :eval never gnuplot plot.pg - #+END_SRC
** Ascii matrix data
#+BEGIN_SRC sh :wrap "src cpp :eval never" :results output :exports results cat $(pwd)/examples/matrix.cpp #+END_SRC
#+RESULTS: #+BEGIN_src cpp :eval never #include "GnuPlotScripting/GnuPlotScripting.hpp"
#include <iostream>
using namespace GnuPlotScripting;
// Example from: https://stackoverflow.com/a/27049991/2001017 // Also see: https://stackoverflow.com/q/32458753/2001017 // int main() { Data_Ascii data( "0.00 0.65 0.65 0.25\n" "0.25 0.00 0.75 0.25\n" "0.50 0.60 0.00 0.25\n" "0.75 0.25 0.10 0.00\n");
Script_File script("matrix.gp");
script.free_form("set autoscale fix"); script.free_form("set cbrange [-1:1]"); script.free_form("unset colorbox"); script.free_form("unset key"); script.free_form( "plot {} matrix using 1:2:3 with image, '' matrix using " "1:2:(sprintf('%.2f', $3)) with labels font ',16'", data); script.export_as(PNG(), "matrix"); script.export_as(EPSLATEX().set_standalone(true), "matrix"); } #+END_src
It generates this figure:
[[file:figures/matrix.png]]
It also generates a standalone =matrix.tex= file you can process with =pdflatex matrix.tex= to get a monochrome =matrix.pdf= file. If you want colorized pdf simply use: #+begin_src cpp :eval never EPSLATEX().set_standalone(true).set_color(true) #+end_src
** (NEW) Matrix data
You can also use the =Array_2= container to temporary store your data
#+BEGIN_SRC sh :wrap "src cpp :eval never" :results output :exports results cat $(pwd)/examples/array_2.cpp #+END_SRC
#+RESULTS: #+begin_src cpp :eval never #include "GnuPlotScripting/array_2.hpp" #include "GnuPlotScripting/GnuPlotScripting.hpp"
#include <iostream>
using namespace GnuPlotScripting;
int main() { const double X = 2, Y = 2; const std::size_t I = 100, J = 120;
const auto f = [=](const std::size_t i, const std::size_t j) { const double x = (2 * i / double(I - 1) - 1) * X; const double y = (2 * j / double(J - 1) - 1) * Y;
return exp(-x * x - y * y);
};
Array_2 array_2(I, J, f);
Data_Array_2 data(array_2);
Script_File script("array_2.gp");
script.free_form("set autoscale fix"); script.free_form("plot {} matrix using 1:2:3 with image", data); script.export_as(PNG(), "array_2"); } #+end_src
It generates this figure:
[[file:figures/array_2.png][file:figures/array_2.png]]
** Histogram
#+BEGIN_SRC sh :wrap "src cpp :eval never" :results output :exports results cat $(pwd)/examples/histogram.cpp #+END_SRC
#+RESULTS: #+BEGIN_src cpp :eval never #include "GnuPlotScripting/GnuPlotScripting.hpp"
#include <iostream> #include <random>
using namespace GnuPlotScripting;
// Example from: // https://stackoverflow.com/a/7454274/2001017 // template <typename T> void gnuplot_histogram(Script& script, const std::vector<T>& data, const size_t n_bin, const typename std::vector<T>::value_type min, const typename std::vector<T>::value_type max) { assert(max > min); assert(n_bin > 0);
Data_Vector gnuplot_data(data);
const double width = (max - min) / n_bin; script.free_form("width={}", width); script.free_form("set title 'Histogram min={}, max={}, Δbin={}, #bins={}, #sample={}'", min, max, width, n_bin, data.size()); script.free_form("hist(x,width)=widthfloor(x/width)+width/2.0"); script.free_form("set boxwidth width0.9"); script.free_form("set style fill solid 0.5"); script.free_form("plot {} u (hist($1,width)):(1.0) smooth freq w boxes notitle", gnuplot_data); }
int main() { std::random_device rd; std::mt19937 gen(rd()); const double a = 2, b = 1; std::gamma_distribution<> distribution(a, b);
std::vector<double> data(10000); for (auto& data_i : data) data_i = distribution(gen);
Script_File script("histogram.gp");
gnuplot_histogram(script, data, 100, 0, 3);
script.export_as(PNG(), "histogram"); } #+END_src
The generated figure is:
[[file:figures/histogram.png]]
** Graph
#+BEGIN_SRC sh :wrap "src cpp :eval never" :results output :exports results cat $(pwd)/examples/graph.cpp #+END_SRC
#+RESULTS: #+BEGIN_src cpp :eval never
#include "GnuPlotScripting/GnuPlotScri
