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 
17 namespace 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:
59  Gnuplot& operator=(Gnuplot&&) = delete;
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
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
Gnuplot & operator=(const Gnuplot &)=delete
void dbvalue(size_t i, const T &t)
Definition: gnuplot.h:25
static void test()
Definition: gnuplot.h:164
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 & operator=(Gnuplot &&)=delete
~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
File holds all helper structures necessary for the CC_Operator and CC2 class.
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