MADNESS 0.10.1
gnuplot.h
Go to the documentation of this file.
1#ifndef MADNESS_GNUPLOT_H__INCUDED
2#define MADNESS_GNUPLOT_H__INCUDED
3
4#include <unistd.h>
5#include <sys/types.h>
6#include <sys/wait.h>
7
8#include <cstdio>
9#include <cstdlib>
10#include <cstring>
11#include <cmath>
12
13#include <iostream>
14#include <string>
15#include <vector>
16
17namespace madness {
18 class Gnuplot {
19 FILE *f; // pipe connection to gnuplot process
20 pid_t pid; // pid of gnuplot process
21 FILE *ftee; // filestream for data tee'd from gnuplot process
22
23 // base case for unpacking datablock value
24 template <typename T>
25 void dbvalue(size_t i, const T& t) {
26 char buf[256];
27 snprintf(buf,sizeof(buf),"%16.8e",double(t[i]));
28 (*this)(buf); // newline
29 }
30
31 // recursion case for unpacking datablock value
32 template <typename T, typename... Ts>
33 void dbvalue(size_t i, const T& t, Ts... values) {
34 char buf[256];
35 snprintf(buf,sizeof(buf),"%16.8e ",double(t[i])); // space
36 (*this)(buf,false);
37 dbvalue(i,values...);
38 }
39
40 // base case for unpacking plot value
41 template <int n, typename T>
42 void doplot(const char* name, const T& value0) {
43 char buf[256];
44 snprintf(buf, sizeof(buf), "%s using 1:%d", name, n);
45 (*this)(buf);
46 }
47
48 // recursion case for unpacking plot value
49 template <int n, typename T, typename... Ts>
50 void doplot(const char* name, const T& value0, Ts... values) {
51 char buf[256];
52 snprintf(buf, sizeof(buf), "%s using 1:%d, ", name, n);
53 (*this)(buf,false);
54
55 doplot<n+1,Ts...>(name, values...);
56 }
57
58 public:
60 Gnuplot& operator=(const Gnuplot&) = delete;
61 Gnuplot(const Gnuplot&) = delete;
62 Gnuplot(const std::string& cmd = "", const std::string& teefile = "") : f(0), ftee(0) {
63 int p[2];
64 if (pipe (p)) {
65 throw "Pipe failed.";
66 }
67 pid = fork ();
68 if (pid == 0) { // Child process.
69 close(p[1]);
70 dup2(p[0],STDIN_FILENO);
71 close(p[0]);
72 if (execlp ("gnuplot", "gnuplot", "-persist", NULL) == -1) {
73 //if (execlp ("cat", "cat", "-", NULL) == -1) {
74 fprintf(stderr,"Gnuplot: execlp failed for gnuplot ... plotting disabled\n");
75 exit(1);
76 }
77 }
78 else if (pid < (pid_t) 0) { // Failure
79 throw "Fork failed.";
80 }
81 else { // Parent process
82 close (p[0]);
83 f = fdopen (p[1], "w");
84 }
85 if (teefile.size() > 0) {
86 ftee = fopen(teefile.c_str(),"w");
87 if (!ftee) {
88 fprintf(stderr,"Gnuplot: fopen failed for tee file %s ... tee of plotting disabled\n",teefile.c_str());
89 }
90 }
91
92 if (cmd.size() > 0) (*this)(cmd);
93 }
94
95 // outputs string to gnuplot process
96 void operator()(const char* cmd, bool EOL=true) {
97
98 if (f) {
99 if (!fprintf(f,"%s",cmd)) {
100 fprintf(stderr,"Gnuplot: failed writing to gnuplot pipe ... plotting disabled\n");
101 fclose(f);
102 f = NULL;
103 }
104 }
105 if (ftee) fprintf(ftee,"%s",cmd);
106
107 const int n = strlen(cmd);
108 if (EOL && ((n==0) || (cmd[n-1] != '\n') ) ) {
109 if (f) {
110 if (!fprintf(f,"\n")) {
111 fprintf(stderr,"Gnuplot: failed writing newline to gnuplot pipe ... plotting disabled\n");
112 fclose(f);
113 f = NULL;
114 }
115 }
116 if (ftee) fprintf(ftee,"\n");
117 }
118 if (f) fflush(f);
119 }
120
121 // outputs string to gnuplot process
122 void operator()(const std::string& cmd, bool EOL=true) {
123 (*this)(cmd.c_str(), EOL);
124 }
125
126 // Define a gnuplot data block with given name assuming 1-d indexing via [] with explicit size
127 template <typename T, typename... Ts>
128 void db(const std::string& name, size_t size, const T& x, Ts... values) {
129 (*this)("$",false);
130 (*this)(name,false);
131 (*this)(" << EOD");
132 for (size_t i = 0; i<size; ++i) {
133 dbvalue(i,x,values...);
134 }
135 (*this)("EOD");
136 }
137
138 // Define a gnuplot data block with given name assuming 1-d indexing via [] with size from x (a 1-d container that supports size())
139 template <typename T, typename... Ts>
140 void db(const std::string& name, const T& x, Ts... values) {
141 db(name,(size_t) x.size(),x,values...); // have to force x.size() to be size_t since Tensor<T>::size() returns long
142 }
143
144 // Plots data in 2 or more vectors by generating the following gnuplot commands:
145 // $data << EOD
146 // <data values>
147 // EOD
148 // plot $data using 1:2, $data using 1:3, ...
149 template <typename T, typename... Ts>
150 void plot(const T& x, Ts... values) {
151 db("data", x, values...);
152 (*this)("plot ",false);
153 doplot<2,Ts...>("$data", values...); // note we peeled off the x values
154 }
155
157 if (f) {
158 fclose(f);
159 waitpid(pid,0,0);
160 }
161 if (ftee) fclose(ftee);
162 }
163
164 static void test() {
165 std::vector<double> x = {1.0,2.0,3.0};
166 std::vector<double> y = {-1.0,-2.0,3.0};
167 std::vector<double> z = {10.0,11.0,12.0};
168 {
169 Gnuplot g("set style data lp; set grid");
170 g.plot(x,y,z);
171 }
172 {
173 Gnuplot g;
174 //g("set term png");
175 //g("set output \"test.png\"");
176 g.db("xyz",x,y,z);
177 g("plot $xyz using 1:2 with linespoints");
178 }
179 {
180 // use x11 to work around bug (https://sourceforge.net/p/gnuplot/bugs/2634/) ... wxt temporarily needs GDK_BACKEND=x11
181 Gnuplot g("set term x11; set xrange [-10:10]; set yrange [0:1]; set grid; set style data l", "test3.gnuplot");
182 size_t npts = 100;
183 std::vector<double> x(npts), y(npts);
184 for (size_t i = 0; i<npts; ++i) x[i] = -10.0 + 20.0 * i / (npts-1);
185 for (int step=0; step<40; step++) {
186 double phase = step*0.3;
187 for (size_t i = 0; i<npts; ++i) y[i] = 0.5 + 0.5 * std::sin(x[i]+phase);
188 char buf[256];
189 snprintf(buf,sizeof(buf),"set title \"step %d\"",step);
190 g(buf);
191 g.plot(x,y);
192 usleep(100000);
193 }
194 }
195 }
196 };
197}
198#endif
Definition gnuplot.h:18
Gnuplot & operator=(Gnuplot &&)=delete
void doplot(const char *name, const T &value0)
Definition gnuplot.h:42
Gnuplot(const std::string &cmd="", const std::string &teefile="")
Definition gnuplot.h:62
void dbvalue(size_t i, const T &t, Ts... values)
Definition gnuplot.h:33
void dbvalue(size_t i, const T &t)
Definition gnuplot.h:25
static void test()
Definition gnuplot.h:164
Gnuplot & operator=(const Gnuplot &)=delete
void db(const std::string &name, const T &x, Ts... values)
Definition gnuplot.h:140
void db(const std::string &name, size_t size, const T &x, Ts... values)
Definition gnuplot.h:128
void doplot(const char *name, const T &value0, Ts... values)
Definition gnuplot.h:50
FILE * f
Definition gnuplot.h:19
void operator()(const char *cmd, bool EOL=true)
Definition gnuplot.h:96
FILE * ftee
Definition gnuplot.h:21
pid_t pid
Definition gnuplot.h:20
Gnuplot(const Gnuplot &)=delete
void operator()(const std::string &cmd, bool EOL=true)
Definition gnuplot.h:122
void plot(const T &x, Ts... values)
Definition gnuplot.h:150
~Gnuplot()
Definition gnuplot.h:156
char * p(char *buf, const char *name, int k, int initial_level, double thresh, int order)
Definition derivatives.cc:72
auto T(World &world, response_space &f) -> response_space
Definition global_functions.cc:34
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
NDIM const Function< R, NDIM > & g
Definition mra.h:2416
std::string name(const FuncType &type, const int ex=-1)
Definition ccpairfunction.h:28
static double phase(long i)
Definition twoscale.cc:85