SigPack - the C++ signal processing library
gplot.h
Go to the documentation of this file.
1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 #ifndef SP_GPLOT_H
5 #define SP_GPLOT_H
6 #include <vector>
7 #include <typeinfo>
8 namespace sp
9 {
14 
25 class gplot
26 {
27 private:
28  FILE *gnucmd;
29  std::string term;
30  int fig_ix;
31  int plot_ix;
32 
33  struct plot_data_s {
34  std::string label;
35  std::string linespec;
36  };
37 
38  std::vector<plot_data_s> plotlist;
39 
45  template <typename T1, typename T2> void plot_str2(const T1 &x, const T2 &y)
46  {
47  std::ostringstream tmp_s;
48  std::string s;
49  tmp_s << "$Dxy" << plot_ix << " << EOD \n";
50  arma::uword Nelem = x.n_elem;
51  for (arma::uword n = 0; n < Nelem; n++)
52  {
53  tmp_s << x(n) << " " << y(n);
54  s = tmp_s.str();
55  send2gp(s.c_str());
56  tmp_s.str(""); // Clear buffer
57  }
58  send2gp("EOD");
59  }
60 
66  template <typename T> std::string get_type(T x)
67  {
68  if (typeid(x) == typeid(int8_t))
69  return "int8";
70  if (typeid(x) == typeid(uint8_t))
71  return "uint8";
72  if (typeid(x) == typeid(int16_t))
73  return "int16";
74  if (typeid(x) == typeid(uint16_t))
75  return "uint16";
76  if (typeid(x) == typeid(int32_t))
77  return "int32";
78  if (typeid(x) == typeid(uint32_t))
79  return "uint32";
80  if (typeid(x) == typeid(int64_t))
81  return "int64";
82  if (typeid(x) == typeid(arma::sword))
83  return "int64";
84  if (typeid(x) == typeid(uint64_t))
85  return "uint64";
86  if (typeid(x) == typeid(arma::uword))
87  return "uint64";
88  if (typeid(x) == typeid(float))
89  return "float32";
90  if (typeid(x) == typeid(double))
91  return "float64";
92  err_handler("Unknown type");
93  }
94 
95 public:
103  {
104 #if defined(_MSC_VER)
105  gnucmd = _popen("gnuplot -persist 2> NUL", "wb");
106  term = "win";
107 //#elif defined(_APPLE_)
108 // gnucmd = popen("gnuplot -persist &> /dev/null","w");
109 //#define term "aqua"
110 #else
111  gnucmd = popen("gnuplot -persist", "w");
112  term = "x11";
113 #endif
114  if (!gnucmd)
115  {
116  err_handler("Could not start gnuplot");
117  }
118 
119  // Set global params
120  plot_ix = 0;
121  fig_ix = 0;
122  plotlist.clear();
123  }
124 
129  {
130 #if defined(_MSC_VER)
131  _pclose(gnucmd);
132 #else
133  pclose(gnucmd);
134 #endif
135  }
136 
141  void send2gp(const char *cmdstr)
142  {
143  std::string s_in(cmdstr);
144  std::string tmp = s_in + "\n";
145  std::fputs(tmp.c_str(), gnucmd);
146  // std::cout << tmp.c_str() << std::endl;
147  }
148 
152  void flush_cmd_buf(void) { std::fflush(gnucmd); }
153 
157  void draw_now(void) { std::fflush(gnucmd); }
158 
163  void figure(const int fig)
164  {
165  fig_ix = fig;
166  std::ostringstream tmp_s;
167  tmp_s << "set term " << term << " " << fig;
168  std::string s = tmp_s.str();
169  send2gp(s.c_str());
170  send2gp("reset");
171  }
172 
182  void window(const int fig, const char *name, const int x, const int y,
183  const int width, const int height)
184  {
185  fig_ix = fig;
186  std::ostringstream tmp_s;
187  tmp_s << "set term " << term << " " << fig << " title \"" << name
188  << "\" position " << x << "," << y << " size " << width << ","
189  << height;
190  std::string s = tmp_s.str();
191  send2gp(s.c_str());
192  send2gp("reset");
193  }
194 
204  void window(const char *name, const int x, const int y, const int width,
205  const int height)
206  {
207  window(0, name, x, y, width, height);
208  }
209 
213  void close_window(void)
214  {
215  std::ostringstream tmp_s;
216  tmp_s << "set term " << term << " close";
217  std::string s = tmp_s.str();
218  send2gp(s.c_str());
219  send2gp("reset");
220  }
221 
225  void grid_on(void) { send2gp("set grid"); }
226 
230  void grid_off(void) { send2gp("unset grid"); }
231 
236  void xlabel(const char *label)
237  {
238  std::ostringstream tmp_s;
239  tmp_s << "set xlabel \"" << label << "\" ";
240  std::string s = tmp_s.str();
241  send2gp(s.c_str());
242  }
243 
248  void ylabel(const char *label)
249  {
250  std::ostringstream tmp_s;
251  tmp_s << "set ylabel \"" << label << "\" ";
252  std::string s = tmp_s.str();
253  send2gp(s.c_str());
254  }
255 
262  void label(const double &x, const double &y, const char *label)
263  {
264  std::ostringstream tmp_s;
265  tmp_s << "set label \"" << label << "\" at " << x << "," << y;
266  std::string s = tmp_s.str();
267  send2gp(s.c_str());
268  }
269 
274  void title(const char *name)
275  {
276  std::ostringstream tmp_s;
277  tmp_s << "set title \"" << name << " \" ";
278  std::string s = tmp_s.str();
279  send2gp(s.c_str());
280  }
281 
287  void xlim(const double xmin, const double xmax)
288  {
289  std::ostringstream tmp_s;
290  tmp_s << "set xrange [" << xmin << ":" << xmax << "]";
291  std::string s = tmp_s.str();
292  send2gp(s.c_str());
293  }
294 
300  void ylim(const double ymin, const double ymax)
301  {
302  std::ostringstream tmp_s;
303  tmp_s << "set yrange [" << ymin << ":" << ymax << "]";
304  std::string s = tmp_s.str();
305  send2gp(s.c_str());
306  }
307 
315  template <typename T1, typename T2>
316  void plot_add(const T1 &x, const T2 &y, const std::string lb,
317  const std::string ls = "lines")
318  {
319  plot_data_s pd;
320 
321  pd.linespec = ls;
322  pd.label = lb;
323 
324  plotlist.push_back(pd);
325  plot_str2(x, y);
326  plot_ix++;
327  }
328 
335  template <typename T1>
336  void plot_add(const T1 &y, const std::string lb,
337  const std::string ls = "lines")
338  {
339  arma::vec x = arma::regspace(0, double(y.n_elem - 1));
340  plot_data_s pd;
341 
342  pd.linespec = ls;
343  pd.label = lb;
344 
345  plotlist.push_back(pd);
346  plot_str2(x, y);
347  plot_ix++;
348  }
349 
354  void plot_add_mat(const arma::mat &y)
355  {
356  arma::vec x = arma::regspace(0, double(y.n_cols - 1));
357  plot_data_s pd;
358 
359  pd.linespec = "lines";
360  pd.label = "";
361  for (arma::uword r = 0; r < y.n_rows; r++)
362  {
363  plotlist.push_back(pd);
364  plot_str2(x, y.row(r));
365  plot_ix++;
366  }
367  }
368 
374  void plot_add_mat(const arma::mat &y, const std::string p_lb)
375  {
376  arma::vec x = arma::regspace(0, double(y.n_cols - 1));
377  plot_data_s pd;
378  pd.linespec = "lines";
379 
380  for (arma::uword r = 0; r < y.n_rows; r++)
381  {
382  std::ostringstream tmp_s;
383  tmp_s << p_lb << r;
384  std::string s = tmp_s.str();
385  pd.label = s;
386  plotlist.push_back(pd);
387  plot_str2(x, y.row(r));
388  plot_ix++;
389  }
390  }
391 
395  void plot_show(void)
396  {
397  std::ostringstream tmp_s;
398 
399  tmp_s << "plot $Dxy0 title \"" << plotlist[0].label << "\" with "
400  << plotlist[0].linespec;
401  for (int r = 1; r < plot_ix; r++)
402  {
403  tmp_s << " ,$Dxy" << r << " title \"" << plotlist[r].label << "\" with "
404  << plotlist[r].linespec;
405  }
406  std::string s = tmp_s.str();
407  send2gp(s.c_str());
408  plotlist.clear();
409  plot_ix = 0;
410  }
411 
415  void plot_clear(void)
416  {
417  plotlist.clear();
418  plot_ix = 0;
419  }
420 
425  template <typename T>
426  void fast_plot(const arma::Col<T> &x,
427  const std::string fmt_args = "with lines")
428  {
429  std::string fmt = get_type(x.at(0));
430  std::string s;
431  send2gp("unset key");
432 
433  s = "plot '-' binary format='%" + fmt + "' array=(" +
434  std::to_string(x.n_elem) + ") " + fmt_args;
435  send2gp(s.c_str());
436  std::fwrite(x.memptr(), sizeof(x.at(0)), x.n_elem, gnucmd);
437  flush_cmd_buf();
438  }
439 
447  template <typename T>
448  void fast_plot(const arma::Col<T> &x, const arma::Col<T> &y,
449  const std::string fmt_args = "with lines")
450  {
451  std::string fmt1 = get_type(x.at(0));
452  std::string s;
453  send2gp("unset key");
454  const arma::uword N = x.n_elem;
455  arma::Col<T> v(2 * N);
456  for (arma::uword n = 0; n < N; n++)
457  {
458  v.at(2 * n) = x.at(n);
459  v.at(2 * n + 1) = y.at(n);
460  }
461 
462  s = "plot '-' binary format='%" + fmt1 + "' record=(" +
463  std::to_string(x.n_elem) + ") " + fmt_args;
464  send2gp(s.c_str());
465  std::fwrite(v.memptr(), sizeof(x.at(0)), v.n_elem, gnucmd);
466  flush_cmd_buf();
467  }
468 
473  template <typename T> void image(const arma::Mat<T> &x)
474  {
475  xlim(-0.5, x.n_cols - 0.5);
476  ylim(x.n_rows - 0.5, -0.5);
477  send2gp("unset key");
478  std::string fmt = get_type(x.at(0));
479  std::string s;
480 
481  s = "plot '-' binary array=(" + std::to_string(x.n_cols) + "," +
482  std::to_string(x.n_rows) + ") scan=yx format='%" + fmt + "' w image";
483  send2gp(s.c_str());
484  std::fwrite(x.memptr(), sizeof(x.at(0)), x.n_elem, gnucmd);
485  flush_cmd_buf();
486  }
487 
492  template <typename T> void image(const arma::Cube<T> &x)
493  {
494  xlim(-0.5, x.n_cols - 0.5);
495  ylim(x.n_rows - 0.5, -0.5);
496  send2gp("unset key");
497  std::string fmt = get_type(x.at(0));
498  std::string s;
499 
500  // Conv cube to gnuplot rgb array
501  arma::Cube<T> gp_im(arma::size(x));
502  T *ptr = gp_im.memptr();
503  for (arma::uword c = 0; c < x.n_cols; c++)
504  {
505  for (arma::uword r = 0; r < x.n_rows; r++)
506  {
507  *ptr++ = x.at(r, c, 0); // R
508  *ptr++ = x.at(r, c, 1); // G
509  *ptr++ = x.at(r, c, 2); // B
510  }
511  }
512 
513  s = "plot '-' binary array=(" + std::to_string(x.n_cols) + "," +
514  std::to_string(x.n_rows) + ") scan=yx format='%" + fmt + "' w rgbimage";
515  send2gp(s.c_str());
516  std::fwrite(gp_im.memptr(), sizeof(x.at(0)), gp_im.n_elem, gnucmd);
517  flush_cmd_buf();
518  }
519 
524  template <typename T> void mesh(const arma::Mat<T> &x)
525  {
526  send2gp("unset key");
527  send2gp("set hidden3d");
528  std::string fmt = get_type(x.at(0));
529  std::string s = "splot '-' binary array=(" + std::to_string(x.n_cols) +
530  "," + std::to_string(x.n_rows) + ") scan=yx format='%" +
531  fmt + "' w lines";
532  send2gp(s.c_str());
533  std::fwrite(x.memptr(), sizeof(x.at(0)), x.n_elem, gnucmd);
534  flush_cmd_buf();
535  }
536 
541  template <typename T> void surf(const arma::Mat<T> &x)
542  {
543  send2gp("set pm3d");
544  mesh(x);
545  }
546 
551  void set_parula_line(void)
552  {
553  send2gp("set linetype 1 lc rgb '#0072bd' "); // blue
554  send2gp("set linetype 2 lc rgb '#d95319' "); // orange
555  send2gp("set linetype 3 lc rgb '#edb120' "); // yellow
556  send2gp("set linetype 4 lc rgb '#7e2f8e' "); // purple
557  send2gp("set linetype 5 lc rgb '#77ac30' "); // green
558  send2gp("set linetype 6 lc rgb '#4dbeee' "); // light-blue
559  send2gp("set linetype 7 lc rgb '#a2142f' "); // red
560  }
561 
566  void set_jet_line(void)
567  {
568  send2gp("set linetype 1 lc rgb '#0000ff' "); // blue
569  send2gp("set linetype 2 lc rgb '#007f00' "); // green
570  send2gp("set linetype 3 lc rgb '#ff0000' "); // red
571  send2gp("set linetype 4 lc rgb '#00bfbf' "); // cyan
572  send2gp("set linetype 5 lc rgb '#bf00bf' "); // pink
573  send2gp("set linetype 6 lc rgb '#bfbf00' "); // yellow
574  send2gp("set linetype 7 lc rgb '#3f3f3f' "); // black
575  }
580  void set_set1_line(void)
581  {
582  send2gp("set linetype 1 lc rgb '#E41A1C' "); // red
583  send2gp("set linetype 2 lc rgb '#377EB8' "); // blue
584  send2gp("set linetype 3 lc rgb '#4DAF4A' "); // green
585  send2gp("set linetype 4 lc rgb '#984EA3' "); // purple
586  send2gp("set linetype 5 lc rgb '#FF7F00' "); // orange
587  send2gp("set linetype 6 lc rgb '#FFFF33' "); // yellow
588  send2gp("set linetype 7 lc rgb '#A65628' "); // brown
589  send2gp("set linetype 8 lc rgb '#F781BF' "); // pink
590 
591  send2gp("set palette maxcolors 8");
592  char str[] = "set palette defined ( \
593  0 '#E41A1C',\
594  1 '#377EB8',\
595  2 '#4DAF4A',\
596  3 '#984EA3',\
597  4 '#FF7F00',\
598  5 '#FFFF33',\
599  6 '#A65628',\
600  7 '#F781BF')";
601  send2gp(str);
602  }
603 
608  void set_jet_palette(void)
609  {
610  char str[] = "set palette defined ( \
611  0 '#000090',\
612  1 '#000fff',\
613  2 '#0090ff',\
614  3 '#0fffee',\
615  4 '#90ff70',\
616  5 '#ffee00',\
617  6 '#ff7000',\
618  7 '#ee0000',\
619  8 '#7f0000')";
620  send2gp(str);
621  }
622 
628  {
629  char str[] = "set palette defined (\
630  0 '#352a87',\
631  1 '#0363e1',\
632  2 '#1485d4',\
633  3 '#06a7c6',\
634  4 '#38b99e',\
635  5 '#92bf73',\
636  6 '#d9ba56',\
637  7 '#fcce2e',\
638  8 '#f9fb0e')";
639  send2gp(str);
640  }
641 
644  // See http://www.kennethmoreland.com/color-advice/
647  {
648  char str[] = "set palette defined (\
649  0 '#5548C1', \
650  1 '#7D87EF', \
651  2 '#A6B9FF', \
652  3 '#CDD7F0', \
653  4 '#EBD1C2', \
654  5 '#F3A889', \
655  6 '#DE6A53', \
656  7 '#B10127')";
657  send2gp(str);
658  }
659 
662  // See http://www.kennethmoreland.com/color-advice/
665  {
666  char str[] = "set palette defined (\
667  0 '#000000', \
668  1 '#2B0F6B', \
669  2 '#5D00CB', \
670  3 '#C60074', \
671  4 '#EB533C', \
672  5 '#F59730', \
673  6 '#E9D839', \
674  7 '#FFFFFF')";
675  send2gp(str);
676  }
677 
695  void set_output(const char *name)
696  {
697  std::string name_s(name);
698  size_t found = name_s.find_last_of(".");
699  std::string ext;
700  ext = name_s.substr(found + 1);
701  std::ostringstream tmp_s;
702 
703  if (ext.compare("png") == 0)
704  {
705  tmp_s << "set terminal pngcairo enhanced font 'Verdana,10'";
706  }
707  else if (ext.compare("ps") == 0)
708  {
709  tmp_s << "set terminal postscript enhanced color";
710  }
711  else if (ext.compare("eps") == 0)
712  {
713  tmp_s << "set terminal postscript eps enhanced color";
714  }
715  else if (ext.compare("tex") == 0)
716  {
717  tmp_s << "set terminal cairolatex eps color enhanced";
718  }
719  else if (ext.compare("pdf") == 0)
720  {
721  tmp_s << "set terminal pdfcairo color enhanced";
722  }
723  else if (ext.compare("svg") == 0)
724  {
725  tmp_s << "set terminal svg enhanced";
726  }
727  else if (ext.compare("emf") == 0)
728  {
729  tmp_s << "set terminal emf color enhanced";
730  }
731  else if (ext.compare("gif") == 0)
732  {
733  tmp_s << "set terminal gif enhanced";
734  }
735  // else if (ext.compare("jpg") == 0)
736  //{
737  // tmp_s << "set terminal jpeg ";
738  //}
739  else
740  {
741  tmp_s << "set terminal " << term;
742  }
743  std::string s = tmp_s.str();
744  send2gp(s.c_str());
745  tmp_s.str(""); // Clear buffer
746  tmp_s << "set output '" << name_s << "'";
747  s = tmp_s.str();
748  send2gp(s.c_str());
749  }
750 
754  void reset_term(void) { send2gp("reset session"); }
755 
759  void set_term(const char *ttype)
760  {
761  std::ostringstream tmp_s;
762  tmp_s << "set terminal " << ttype;
763  std::string s = tmp_s.str();
764  term = s;
765  send2gp(s.c_str());
766  }
767 
768 }; // End Gnuplot Class
769 
771 
772 } // namespace sp
773 #endif
void set_set1_line(void)
Set linetype to Matlab &#39;parula&#39; NB! doesn&#39;t work with X11 -terminal Data from https://github.com/Gnuplotting/gnuplot-palettes.
Definition: gplot.h:580
std::string label
Definition: gplot.h:34
void draw_now(void)
Updates gnuplot instantly. (Flushes the command buffer)
Definition: gplot.h:157
void set_output(const char *name)
Save plot to file.
Definition: gplot.h:695
void reset_term(void)
Reset output terminal.
Definition: gplot.h:754
void set_jet_line(void)
Set linetype to Matlab &#39;jet&#39; NB! doesn&#39;t work with X11 -terminal Data from https://github.com/Gnuplotting/gnuplot-palettes.
Definition: gplot.h:566
int plot_ix
Definition: gplot.h:31
std::string get_type(T x)
Get type.
Definition: gplot.h:66
void fast_plot(const arma::Col< T > &x, const arma::Col< T > &y, const std::string fmt_args="with lines")
Plot vector, fast version.
Definition: gplot.h:448
void flush_cmd_buf(void)
Flush command buffer to Gnuplot pipe.
Definition: gplot.h:152
Gnuplot class.
Definition: gplot.h:25
std::vector< plot_data_s > plotlist
Definition: gplot.h:38
void plot_add_mat(const arma::mat &y, const std::string p_lb)
Push multiple plot, each row gives a plot with prefix label.
Definition: gplot.h:374
void surf(const arma::Mat< T > &x)
Plot mat as surf.
Definition: gplot.h:541
void plot_add(const T1 &y, const std::string lb, const std::string ls="lines")
Push plot y vs. x with label and linespec.
Definition: gplot.h:336
#define err_handler(msg)
Definition: base.h:213
void set_blackbody_palette(void)
Set palette to &#39;black body&#39;.
Definition: gplot.h:664
void grid_off(void)
Set grid.
Definition: gplot.h:230
Definition: base.h:7
void fast_plot(const arma::Col< T > &x, const std::string fmt_args="with lines")
Plot vector, fast version.
Definition: gplot.h:426
std::string linespec
Definition: gplot.h:35
void xlim(const double xmin, const double xmax)
Set X-axis range.
Definition: gplot.h:287
void set_jet_palette(void)
Set palette to Matlab &#39;jet&#39; Data from https://github.com/Gnuplotting/gnuplot-palettes.
Definition: gplot.h:608
void plot_show(void)
Show plots.
Definition: gplot.h:395
void plot_add_mat(const arma::mat &y)
Push multiple plot, each row gives a plot without label.
Definition: gplot.h:354
void grid_on(void)
Set grid.
Definition: gplot.h:225
void set_coolwarm_palette(void)
Set palette to &#39;cool-warm&#39;.
Definition: gplot.h:646
FILE * gnucmd
File handle to pipe.
Definition: gplot.h:28
std::string term
Definition: gplot.h:29
void plot_str2(const T1 &x, const T2 &y)
Plot y vs. x.
Definition: gplot.h:45
void ylabel(const char *label)
Set label for X-axis.
Definition: gplot.h:248
void set_parula_palette(void)
Set palette to Matlab &#39;parula&#39; Data from https://github.com/Gnuplotting/gnuplot-palettes.
Definition: gplot.h:627
void figure(const int fig)
Sets the active figure.
Definition: gplot.h:163
void label(const double &x, const double &y, const char *label)
Set label at position x,y.
Definition: gplot.h:262
void set_parula_line(void)
Set linetype to Matlab &#39;parula&#39; NB! doesn&#39;t work with X11 -terminal Data from https://github.com/Gnuplotting/gnuplot-palettes.
Definition: gplot.h:551
void image(const arma::Mat< T > &x)
Plot mat as image.
Definition: gplot.h:473
void plot_clear(void)
Clear plots.
Definition: gplot.h:415
void set_term(const char *ttype)
Set output terminal.
Definition: gplot.h:759
void image(const arma::Cube< T > &x)
Plot cube as image.
Definition: gplot.h:492
gplot()
Constructor.
Definition: gplot.h:102
~gplot()
Destructor.
Definition: gplot.h:128
void window(const int fig, const char *name, const int x, const int y, const int width, const int height)
Configure the figure used Windows environment.
Definition: gplot.h:182
void xlabel(const char *label)
Set label for X-axis.
Definition: gplot.h:236
void ylim(const double ymin, const double ymax)
Set Y-axis range.
Definition: gplot.h:300
void plot_add(const T1 &x, const T2 &y, const std::string lb, const std::string ls="lines")
Push plot y vs. x with label and linespec.
Definition: gplot.h:316
void mesh(const arma::Mat< T > &x)
Plot mat as mesh.
Definition: gplot.h:524
void window(const char *name, const int x, const int y, const int width, const int height)
Configure the figure/window - used in Linux environment where no figure numbers are needed...
Definition: gplot.h:204
void close_window(void)
Close window.
Definition: gplot.h:213
void title(const char *name)
Set windowtitle.
Definition: gplot.h:274
int fig_ix
Definition: gplot.h:30
void send2gp(const char *cmdstr)
Send command to Gnuplot pipe.
Definition: gplot.h:141