mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
gnuPlot.hpp
Go to the documentation of this file.
1 /** \file gnuPlot.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Declaration and definition of an interface to the gnuplot program
4  * \ingroup plotting_files
5  *
6 */
7 
8 //***********************************************************************//
9 // Copyright 2015-2023 Jared R. Males (jaredmales@gmail.com)
10 //
11 // This file is part of mxlib.
12 //
13 // mxlib is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // mxlib is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 //***********************************************************************//
26 
27 #ifndef math_plot_gnuPlot_hpp
28 #define math_plot_gnuPlot_hpp
29 
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <poll.h>
36 
37 #include <stdlib.h>
38 
39 #include <string>
40 #include <iostream>
41 #include <fstream>
42 #include <vector>
43 
44 #include <cmath>
45 
46 #include <map>
47 
48 #include "../constants.hpp"
49 #include "../../mxError.hpp"
50 #include "../../sys/timeUtils.hpp"
51 
52 #ifndef MX_GP_FNAME_SZ
53 ///The size of the string for managing the stderr fifo
54 /** \ingroup plotting
55  */
56 #define MX_GP_FNAME_SZ (128)
57 #endif
58 
59 #ifndef MX_GP_TEMP_SZ
60 ///The size of the string for managing temporary file names
61 /** \ingroup plotting
62  */
63 #define MX_GP_TEMP_SZ (128)
64 #endif
65 
66 #ifndef MX_GP_FC_TIME
67 /** \def MX_GP_FC_TIME
68  * Time, in microseconds, to wait for gnuplot startup and file creation to complete.
69  * Opening is retried after each timeout of this length for MX_GP_FC_RETRIES attempts.
70  * \ingroup plotting
71  */
72 #define MX_GP_FC_TIME (10000)
73 #endif
74 
75 #ifndef MX_GP_FC_RETRIES
76 /** \def MX_GP_FC_RETRIES
77  * Number of times to retry opening the gnuplot stderr file.
78  * \ingroup plotting
79  */
80 #define MX_GP_FC_RETRIES (10)
81 #endif
82 
83 namespace mx
84 {
85 namespace math
86 {
87 
88 
89 //Get the gnuplot binary format string for a type
90 //Specializations below.
91 template<typename dataT>
92 std::string gpBinaryFormat()
93 {
94  static_assert(std::is_fundamental<dataT>::value || !std::is_fundamental<dataT>::value, "No gnuplot format specifier available for this type.");
95  return "";
96 }
97 
98 struct gpCurve
99 {
100  std::string m_file;
101 
102  std::string m_title;
103 
104  std::string m_modifiers;
105 
106  std::string m_binary;
107 
108  gpCurve(){}
109 
110  gpCurve( const std::string & file,
111  const std::string & title,
112  const std::string & modifiers
113  ) : m_file(file), m_title(title), m_modifiers(modifiers)
114  {}
115 
116  gpCurve( const std::string & file,
117  const std::string & title,
118  const std::string & modifiers,
119  const std::string & binary
120  ) : m_file(file), m_title(title), m_modifiers(modifiers), m_binary(binary)
121  {}
122 
123  gpCurve( const gpCurve & gpc )
124  {
125  m_file = gpc.m_file;
126  m_title = gpc.m_title;
127  m_modifiers = gpc.m_modifiers;
128  m_binary = gpc.m_binary;
129  }
130 
131 };
132 
133 /// An interactive c++ interface to gnuplot
134 /** Spawns a gnuplot sesssion and communicates with it.
135  * \ingroup plotting
136  *
137  * \todo Use mxError for error reporting.
138  *
139  * An example of using gnuPlot to plot data from a file:
140  * \code
141  * gnuPlot gp; //This automatically connects, and is now ready to plot.
142  *
143  * gp.plot("my_data_file.dat", "u 1:2 w l"); //Plots the data in the file
144  * \endcode
145  *
146  * Arrays can be plotted directly:
147  * \code
148  * std::vector<float> x;
149  * std::vector<double> y;
150  *
151  * //...code to populate x and y
152  *
153  * gp.plot(x, y); //Plots y vs x.
154  * \endcode
155  * Note that the vector data types are different -- this is handled automatically.
156  *
157  * To get a response from the gnuplot session:
158  * \code
159  * std::cout << gp.getResponse("show terminal") << "\n"; //Sends the command to gnuplot, gets the response.
160  * \endcode
161  * Error checking and reporting is not straightforward since gnuplot does not return a result if there is no error. If there is an error,
162  * it can take several hundred milliseconds for a response to be available. So for a typical
163  * plot command, say, one does not want to try to read the stderr ouput just in case as this will just time out with a delay.
164  *
165  * For cases where a response is expected, the following example shows how to check for errors.
166  * \code
167  * errno = 0;
168  * std::string response = gp.getResponse("show terminal"); //Waits up to 0.5 seconds, or a user specified timeout.
169  *
170  * if(response == "") //This indicates some error occurred, or a timeout.
171  * {
172  * if(gp.gpError())
173  * {
174  * std::cerr << "gnuplot returned error:\n" << gp.gpErrorMsg() << "\n";
175  * }
176  * else if(errno)
177  * {
178  * perror("error getting response: ");
179  * }
180  * else
181  * {
182  * std::cerr << "timed out\n";
183  * }
184  * }
185  * else
186  * {
187  * std::cout << response << "\n";
188  * }
189  *
190  * \endcode
191  */
192 class gnuPlot
193 {
194 protected:
195 
196  int _connected {0};
197 
198  ///Set to true if the response indicates a gnuplot error
199  bool _gpError {false};
200  std::string _gpErrorMsg;
201 
202  ///File stream for the gnuplot interface
203  FILE * _pipeH {0};
204 
205  ///Where to create gnuplot stderr fifo
206  /** Default is /dev/shm/
207  */
208  std::string _errLocation;
209 
210  ///File name of the gnuplot stderr fifo
211  std::string _errFName;
212 
213  ///File descriptor for the gnuplot stderr fifo
214  int _errFD {0};
215 
216  ///Location of temporary files
217  /** Default is /dev/shm/
218  */
219  std::string _tempLocation;
220 
221  ///Vector of all temporary file names opened, used for removal on destruction.
222  std::vector<std::string> _tempFiles;
223 
224  ///Flag to control whether temporary files are deleted on destruction. Default is true (files deleted).
225  bool _deleteTemp {true};
226 
227  std::map<std::string, gpCurve> m_curveMap;
228 
229 public:
230 
231  gnuPlot();
232 
233  ~gnuPlot();
234 
235  ///Connect to gnuplot
236  /** Spawns a gnuplot session using popen with stderr redirected to a temporary file. The temporary file
237  * is opened for reading.
238  *
239  * \retval 0 on success
240  * \retval -1 on error
241  */
242  int connect();
243 
244  ///Return the value of the gpError flag.
245  /** This flag is set if gnuplot returns an error message (see checkResponse()). The error message
246  * can be accessed with gpErrorMsg().
247  *
248  * \retval 0 if no error
249  * \retval -1 if an error has occurred.
250  */
251  bool gpError();
252 
253  ///Return the gnuplot error message
254  /** The error message is extracted by checkResponse() when the response from gnuplot begins with "gnuplot>".
255  */
256  std::string gpErrorMsg();
257 
258  ///Send a command to gnuplot
259  /** The newline is appended to the command, and then it is sent to gnuplot.
260  *
261  *
262  * \retval 0 on success
263  * \retval -1 on error
264  */
265  int command( const std::string & com, ///< [in] the command string
266  bool flush = true ///< [in] [optional] if true (default), then the output stream is flushed once the command is written
267  );
268 
269  ///Check for a response from gnuplot.
270  /** It typically takes some time for a response from gnuplot to become readable,
271  * whether an error occurs or not. It is often 0.3 seconds or more. If there is no error, there will be no response so waiting
272  * for a response to check for errors after every command can be very time consuming. Thus it is a choice whether to check
273  * for errors from gnuplot after every command, and what timeout to use.
274  *
275  * \todo investigate having a second thread monitor for responses.
276  *
277  * gnuplot terminates all outputs with \c \\n\\n, so this reads up to these two characters. It then strips any leading and trailing whitespace.
278  * If the response begins with \c gnuplot>, then the response is an error. In this case, checkResponse returns -1 and the gpError flag is set. If gpError is not set
279  * but the return value is -1, then some other error occurred (check \c errno).
280  *
281  * \retval 0 on timeout or successful read
282  * \retval -1 on error, or if the gnuplot response indicates an error.
283  */
284  int checkResponse( std::string & response, ///< [out] contains the response from gnuplot, but is empty on timeout or error.
285  double timeout = 0 ///< [in] [optional] the length of time, in seconds, to wait for a response. Default is 0, but a minimum of 0.5 if a response is expected.
286  );
287 
288  ///Get a response from gnuplot for a given command.
289  /** This should only be used if a response is expected.
290  *
291  * \returns "" (empty string) on timeout or error (\c errno and gpError() should be checked), and the response from gnuplot otherwise.
292  */
293  std::string getResponse( const std::string & com, ///< [in] the command string
294  double timeout=0.5 ///< [in] the length of time, in seconds, to wait for a response. Default is 0.5, which is the minimum that should be used.
295  );
296 
297 
298  /// Issue the \b replot command
299  /**
300  * \retval 0 on success
301  * \retval -1 on error
302  */
303  int replot();
304 
305  /// Set the x-axis range
306  /** Sends the command:
307  * \verbatim
308  * set xrange [x0:x1]
309  * \endverbatim
310  *
311  * \returns 0 on success
312  * \returns -1 on error
313  */
314  int xrange( double x0,
315  double x1
316  );
317 
318  /// Unset the x-axis range
319  /** Sends the command:
320  * \verbatim
321  * unset xrange
322  * \endverbatim
323  *
324  * \returns 0 on success
325  * \returns -1 on error
326  */
327  int xrange();
328 
329  /// Set the y-axis range
330  /** Sends the command:
331  * \verbatim
332  * set yrange [y0:y1]
333  * \endverbatim
334  *
335  * \returns 0 on success
336  * \returns -1 on error
337  */
338  int yrange( double y0,
339  double y1
340  );
341 
342  /// Unset the y-axis range
343  /** Sends the command:
344  * \verbatim
345  * unset yrange
346  * \endverbatim
347  *
348  * \returns 0 on success
349  * \returns -1 on error
350  */
351  int yrange();
352 
353  /// Set the y axis to log scale
354  /** Sends the command:
355  * \verbatim
356  set log y
357  \endverbatim
358  *
359  * \retval 0 on success
360  * \retval -1 on error
361  */
362  int logy();
363 
364  /// Set the x axis to log scale
365  /** Sends the command:
366  * \verbatim
367  set log x
368  \endverbatim
369  *
370  * \retval 0 on success
371  * \retval -1 on error
372  */
373  int logx();
374 
375  /// Set the x and y axes to log scale
376  /** Sends the commands:
377  * \verbatim
378  set log x
379  set log y
380  \endverbatim
381  *
382  * \retval 0 on success
383  * \retval -1 on error
384  */
385  int logxy();
386 
387  /// Unset the y axis from log scale
388  /** Sends the command:
389  * \verbatim
390  unset log y
391  \endverbatim
392  *
393  * \retval 0 on success
394  * \retval -1 on error
395  */
396  int ulogy();
397 
398  /// Unset the x axis from log scale
399  /** Sends the command:
400  * \verbatim
401  unset log x
402  \endverbatim
403  *
404  * \retval 0 on success
405  * \retval -1 on error
406  */
407  int ulogx();
408 
409  /// Unset the x and y axes from log scale
410  /** Sends the command:
411  * \verbatim
412  unset log x
413  unset log y
414  \endverbatim
415  *
416  * \retval 0 on success
417  * \retval -1 on error
418  */
419  int ulogxy();
420 
421  /// Plot from a file specifying all curve components.
422  /** Forms the gnuplot plot command as follows:
423  * \verbatim
424  * plot '<fname>' <modifiers> t '<title>'
425  * \endverbatim
426  * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
427  *
428  * \retval 0 on success
429  * \retval -1 on error
430  */
431  int plot( const std::string & fname, ///< [in] the name (with full path) of the file containing data to plot
432  const std::string & modifiers, ///< [in] contains any modifiers to the plot command.
433  const std::string & title, ///< [in] the title for this curve
434  const std::string & name ///< [in] the name for this curve. If "" then curve# is used.
435  );
436 
437  /// Plot from a file without specifying the title
438  /** Forms the gnuplot plot command as follows:
439  * \verbatim
440  * plot '<fname>' <modifiers> t ''
441  * \endverbatim
442  * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
443  *
444  * \retval 0 on success
445  * \retval -1 on error
446  *
447  * \overload
448  */
449  int plot( const std::string & fname, ///< [in] the name (with full path) of the file containing data to plot
450  const std::string & modifiers, ///< [in] contains any modifiers to the plot command.
451  const std::string & name ///< [in] the name for this curve. If "" then the curve# is used.
452  );
453 
454  /// Plot from a file without modifiers
455  /** The file name is used for the identifying name
456  *
457  * Forms the gnuplot plot command as follows:
458  * \verbatim
459  * plot '<fname>' <modifiers> t ''
460  * \endverbatim
461  * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
462  *
463  * \retval 0 on success
464  * \retval -1 on error
465  *
466  * \overload
467  */
468  int plot( const std::string & fname, ///< [in] the name (with full path) of the file containing data to plot
469  const std::string & name ///< [in] the name for this curve. If "" then the curve# is used
470  );
471 
472  /// Plot from a file without specifying the name or any modifiers
473  /** The file name is used for the identifying name
474  *
475  * Forms the gnuplot plot command as follows:
476  * \verbatim
477  * plot '<fname>' t ''
478  * \endverbatim
479  * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
480  *
481  * \retval 0 on success
482  * \retval -1 on error
483  *
484  * \overload
485  */
486  int plot( const std::string & fname /**< [in] the name (with full path) of the file containing data to plot */ );
487 
488  /// Plot data from an array
489  /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
490  * \verbatim
491  * plot "temp-file-name" binary format="%dataT" u 1 t "title" <modifiers>
492  * \endverbatim
493  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
494  * specified so that the name of the temporary file name is not printed on the plot.
495  *
496  * \retval 0 on success
497  * \retval -1 on error
498  */
499  template<typename dataT>
500  int plot( const dataT * y, ///< [in] a pointer to an array of data
501  size_t N, ///< [in] the length of the array
502  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
503  const std::string & title, ///< [in] contains the title of the data set, default is an empty string and no key on the plot
504  const std::string & name ///< [in] the identifying name of this curve
505  );
506 
507  /// Plot data from an array
508  /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
509  * \verbatim
510  * plot "temp-file-name" binary format="%dataT" u 1 t '' <modifiers>
511  * \endverbatim
512  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
513  * specified so that the name of the temporary file name is not printed on the plot.
514  *
515  * \retval 0 on success
516  * \retval -1 on error
517  */
518  template<typename dataT>
519  int plot( const dataT * y, ///< [in] a pointer to an array of data
520  size_t N, ///< [in] the length of the array
521  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
522  const std::string & name ///< [in] the identifying name of this curve
523  );
524 
525  /// Plot data from an array
526  /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
527  * \verbatim
528  * plot "temp-file-name" binary format="%dataT" u 1 t '' <modifiers>
529  * \endverbatim
530  *
531  *
532  * \retval 0 on success
533  * \retval -1 on error
534  */
535  template<typename dataT>
536  int plot( const dataT * y, ///< [in] a pointer to an array of data
537  size_t N, ///< [in] the length of the array
538  const std::string & name ///< [in] the identifying name of this curve
539  );
540 
541  /// Plot data from an array
542  /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
543  * \verbatim
544  * plot "temp-file-name" binary format="%dataT" u 1 t ''
545  * \endverbatim
546  *
547  * \retval 0 on success
548  * \retval -1 on error
549  */
550  template<typename dataT>
551  int plot( const dataT * y, ///< [in] a pointer to an array of data
552  size_t N ///< [in] the length of the array
553  );
554 
555 
556 
557  /// Plot data from a vector
558  /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
559  * \verbatim
560  * plot "temp-file-name" binary format="%dataT" u 1 t "title" <modifiers>
561  * \endverbatim
562  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
563  * specified so that the name of the temporary file name is not printed on the plot.
564  *
565  * \retval 0 on success
566  * \retval -1 on error
567  */
568  template<typename dataT>
569  int plot( const std::vector<dataT> & y, ///< [in] the vector containing the data
570  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
571  const std::string & title, ///< [in] contains the title of the data set, default is an empty string and no key on the plot
572  const std::string & name ///< [in] the identifying name of this curve
573  );
574 
575  /// Plot data from a vector
576  /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
577  * \verbatim
578  * plot "temp-file-name" binary format="%dataT" u 1 t '' <modifiers>
579  * \endverbatim
580  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
581  * specified so that the name of the temporary file name is not printed on the plot.
582  *
583  * \retval 0 on success
584  * \retval -1 on error
585  */
586  template<typename dataT>
587  int plot( const std::vector<dataT> & y, ///< [in] the vector containing the data
588  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
589  const std::string & name ///< [in] the identifying name of this curve
590  );
591 
592  /// Plot data from a vector
593  /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
594  * \verbatim
595  * plot "temp-file-name" binary format="%dataT" u 1 t ''
596  * \endverbatim
597  *
598  * \retval 0 on success
599  * \retval -1 on error
600  */
601  template<typename dataT>
602  int plot( const std::vector<dataT> & y, ///< [in] the vector containing the data
603  const std::string & name ///< [in] the identifying name of this curve
604  );
605 
606  /// Plot data from a vector
607  /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
608  * \verbatim
609  * plot "temp-file-name" binary format="%dataT" u 1 t ''
610  * \endverbatim
611  *
612  * \retval 0 on success
613  * \retval -1 on error
614  */
615  template<typename dataT>
616  int plot( const std::vector<dataT> & y /**< [in] the vector containing the data*/);
617 
618 
619  /// Plot y vs. x data from arrays
620  /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
621  * \verbatim
622  plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t "title" <modifiers>
623  \endverbatim
624  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
625  * specified so that the name of the temporary file name is not printed on the plot.
626  *
627  * \retval 0 on success
628  * \retval -1 on error
629  */
630  template<typename dataTx, typename dataTy>
631  int plot( const dataTx * x, ///< [in] a pointer to an array of data for the independent variable
632  const dataTy * y, ///< [in] a pointer to an array of data for the dependent variable
633  size_t N, ///< [in] the length of the arrays
634  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
635  const std::string & title, ///< [in] contains the title of the data set
636  const std::string & name ///< [in] the identifying name of the curve
637  );
638 
639  /// Plot y vs. x data from arrays
640  /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
641  * \verbatim
642  * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t '' <modifiers>
643  * \endverbatim
644  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
645  * specified so that the name of the temporary file name is not printed on the plot.
646  *
647  * \retval 0 on success
648  * \retval -1 on error
649  */
650  template<typename dataTx, typename dataTy>
651  int plot( const dataTx * x, ///< [in] a pointer to an array of data for the independent variable
652  const dataTy * y, ///< [in] a pointer to an array of data for the dependent variable
653  size_t N, ///< [in] the length of the arrays
654  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
655  const std::string & name ///< [in] the identifying name of the curve
656  );
657 
658  /// Plot y vs. x data from arrays
659  /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
660  * \verbatim
661  * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
662  * \endverbatim
663  *
664  * \retval 0 on success
665  * \retval -1 on error
666  */
667  template<typename dataTx, typename dataTy>
668  int plot( const dataTx * x, ///< [in] a pointer to an array of data for the independent variable
669  const dataTy * y, ///< [in] a pointer to an array of data for the dependent variable
670  size_t N, ///< [in] the length of the arrays
671  const std::string & name ///< [in] the identifying name of the curve
672  );
673 
674  /// Plot y vs. x data from arrays
675  /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
676  * \verbatim
677  * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
678  * \endverbatim
679  *
680  * \retval 0 on success
681  * \retval -1 on error
682  */
683  template<typename dataTx, typename dataTy>
684  int plot( const dataTx * x, ///< [in] a pointer to an array of data for the independent variable
685  const dataTy * y, ///< [in] a pointer to an array of data for the dependent variable
686  size_t N ///< [in] the length of the arrays
687  );
688 
689 
690  /// Plot y vs. x data from vectors
691  /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
692  * \verbatim
693  plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t "title" <modifiers>
694  \endverbatim
695  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
696  * specified so that the name of the temporary file name is not printed on the plot.
697  *
698  * \retval 0 on success
699  * \retval -1 on error
700  */
701  template<typename dataTx, typename dataTy>
702  int plot( const std::vector<dataTx> & x, ///< [in] a vector of data for the independent variable
703  const std::vector<dataTy> & y, ///< [in] a vector of data for the dependent variable
704  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
705  const std::string & title, ///< [in] contains the title of the data set
706  const std::string & name ///< [in] the identifying name of the curve
707  );
708 
709  /// Plot y vs. x data from vectors
710  /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
711  * \verbatim
712  plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t '' <modifiers>
713  \endverbatim
714  * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but can contain any other modifiers. Title is
715  * specified so that the name of the temporary file name is not printed on the plot.
716  *
717  * \retval 0 on success
718  * \retval -1 on error
719  */
720  template<typename dataTx, typename dataTy>
721  int plot( const std::vector<dataTx> & x, ///< [in] a vector of data for the independent variable
722  const std::vector<dataTy> & y, ///< [in] a vector of data for the dependent variable
723  const std::string & modifiers, ///< [in] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
724  const std::string & name ///< [in] the identifying name of the curve
725  );
726 
727  /// Plot y vs. x data from vectors
728  /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
729  * \verbatim
730  * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
731  * \endverbatim
732  *
733  * \retval 0 on success
734  * \retval -1 on error
735  */
736  template<typename dataTx, typename dataTy>
737  int plot( const std::vector<dataTx> & x, ///< [in] a vector of data for the independent variable
738  const std::vector<dataTy> & y, ///< [in] a vector of data for the dependent variable
739  const std::string & name ///< [in] the identifying name of the curve
740  );
741 
742  /// Plot y vs. x data from vectors
743  /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
744  * \verbatim
745  * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
746  * \endverbatim
747  *
748  * \retval 0 on success
749  * \retval -1 on error
750  */
751  template<typename dataTx, typename dataTy>
752  int plot( const std::vector<dataTx> & x, ///< [in] a vector of data for the independent variable
753  const std::vector<dataTy> & y ///< [in] a vector of data for the dependent variable
754  );
755 
756 
757  /// Plot a single point
758  /** Copies the position as a length-1 vector to a temporary binary file, and then plots it.
759  *
760  *
761  * \retval 0 on success
762  * \retval -1 on error
763  */
764  template<typename dataTx, typename dataTy>
765  int point( dataTx x, ///< [in] the independent axis (x) coordinate of the point
766  dataTy y, ///< [in] the dependent axis (y) coordinate of the point
767  const std::string & modifiers = "", ///< [in] [optional] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
768  const std::string & title = "" ///< [in] [optional] contains the title of the data set, default is an empty string and no key on the plot
769  );
770 
771  /// Draw a circle on the plot
772  /** Creates a circle with specified center and radius, and plots it.
773  */
774  int circle( double xcen, ///< [in] the x-coordinate of the circle center
775  double ycen, ///< [in] the y-coordinate of the circle center
776  double radius, ///< [in] the circle radius
777  const std::string & modifiers = "", ///< [in] [optional] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
778  const std::string & title = "", ///< [in] [optional] contains the title of the data set, default is an empty string and no key on the plot
779  int npoints = 10 ///< [in] [optional] specifies the number of points in each half circle. Default 10 is usually sufficient.
780  );
781 
782  /// Draw a circle on the plot around the origin
783  /** Creates a circle with radius and center (0,0), and plots it.
784  */
785  int circle( double radius, ///< [in] the circle radius
786  const std::string & modifiers = "", ///< [in] [optional] contains any modifiers to the plot command other than \b binary, \b format, \b using, and \b title.
787  const std::string & title = "", ///< [in] [optional] contains the title of the data set, default is an empty string and no key on the plot
788  int npoints = 10 ///< [in] [optional] specifies the number of points in each half circle. Default 10 is usually sufficient.
789  );
790 
791  /// Clear all the curves
792  void clear();
793 
794  /// Clear all the curves and reset plot configuration
795  void reset();
796 
797  /// List the curves and their specifications.
798  void listCurves();
799 
800  /// Modify the modifiers for a curve
801  void modifiers( const std::string & name, ///< [in] the name of the curve
802  const std::string & modifiers ///< [in] the new modifiers
803  );
804 
805  /// Modify the title for a curve
806  void title( const std::string & name, ///< [in] the name of the curve
807  const std::string & title ///< [in] the new title
808  );
809 
810 protected:
811 
812  /// Implementation of 1-D binary plotting.
813  int plotImpl( const void * y,
814  size_t Nbytes,
815  const std::string & binary,
816  const std::string & modifiers,
817  const std::string & title,
818  const std::string & name
819  );
820 
821  /// Implementation of 2-d binary plotting.
822  int plotImpl( const void * x,
823  const void * y,
824  size_t Npts,
825  size_t sizex,
826  size_t sizey,
827  const std::string & binaryx,
828  const std::string & binaryy,
829  const std::string & modifiers,
830  const std::string & title,
831  const std::string & name
832  );
833 
834  /// Issue the plot command for all the curves
836 
837  ///Open a temporary binary file, and provide the filename.
838  FILE * openTempFile(char * fname);
839 
840 
841 
842 private:
843  ///Initialize an instance, only used at construction
844  void init();
845 
846 
847 };
848 
849 
850 
851 template<typename dataT>
852 int gnuPlot::plot( const dataT * y,
853  size_t N,
854  const std::string & modifiers,
855  const std::string & title,
856  const std::string & name
857  )
858 {
859  return plotImpl(y, N*sizeof(dataT), gpBinaryFormat<dataT>(), modifiers, title, name);
860 }
861 
862 template<typename dataT>
863 int gnuPlot::plot( const dataT * y,
864  size_t N,
865  const std::string & modifiers,
866  const std::string & name
867  )
868 {
869  return plotImpl(y, N*sizeof(dataT), gpBinaryFormat<dataT>(), modifiers, "", name);
870 }
871 
872 template<typename dataT>
873 int gnuPlot::plot( const dataT * y,
874  size_t N,
875  const std::string & name
876  )
877 {
878  return plotImpl(y, N*sizeof(dataT), gpBinaryFormat<dataT>(), "", "", name);
879 }
880 
881 template<typename dataT>
882 int gnuPlot::plot( const dataT * y,
883  size_t N
884  )
885 {
886  return plotImpl(y, N*sizeof(dataT), gpBinaryFormat<dataT>(), "", "", "");
887 }
888 
889 template<typename dataT>
890 int gnuPlot::plot( const std::vector<dataT> & y,
891  const std::string & modifiers,
892  const std::string & title,
893  const std::string & name
894  )
895 {
896  return plot<dataT>( y.data(), y.size(), modifiers, title, name);
897 }
898 
899 template<typename dataT>
900 int gnuPlot::plot( const std::vector<dataT> & y,
901  const std::string & modifiers,
902  const std::string & name
903  )
904 {
905  return plot<dataT>( y.data(), y.size(), modifiers, "", name);
906 }
907 
908 template<typename dataT>
909 int gnuPlot::plot( const std::vector<dataT> & y,
910  const std::string & name
911  )
912 {
913  return plot<dataT>( y.data(), y.size(), "", "", name);
914 }
915 
916 template<typename dataT>
917 int gnuPlot::plot( const std::vector<dataT> & y)
918 {
919  return plot<dataT>( y.data(), y.size(), "", "", "");
920 }
921 
922 
923 template<typename dataTx, typename dataTy>
924 int gnuPlot::plot( const dataTx * x,
925  const dataTy * y,
926  size_t N,
927  const std::string & modifiers,
928  const std::string & title,
929  const std::string & name
930  )
931 {
932  return plotImpl(x, y, N, sizeof(dataTx), sizeof(dataTy), gpBinaryFormat<dataTx>(), gpBinaryFormat<dataTy>(), modifiers, title, name);
933 }
934 
935 template<typename dataTx, typename dataTy>
936 int gnuPlot::plot( const dataTx * x,
937  const dataTy * y,
938  size_t N,
939  const std::string & modifiers,
940  const std::string & name
941  )
942 {
943  return plotImpl(x, y, N, sizeof(dataTx), sizeof(dataTy), gpBinaryFormat<dataTx>(), gpBinaryFormat<dataTy>(), modifiers, "", name);
944 }
945 
946 template<typename dataTx, typename dataTy>
947 int gnuPlot::plot( const dataTx * x,
948  const dataTy * y,
949  size_t N,
950  const std::string & name
951  )
952 {
953  return plotImpl(x, y, N, sizeof(dataTx), sizeof(dataTy), gpBinaryFormat<dataTx>(), gpBinaryFormat<dataTy>(), "", "", name);
954 }
955 
956 template<typename dataTx, typename dataTy>
957 int gnuPlot::plot( const dataTx * x,
958  const dataTy * y,
959  size_t N
960  )
961 {
962  return plotImpl(x, y, N, sizeof(dataTx), sizeof(dataTy), gpBinaryFormat<dataTx>(), gpBinaryFormat<dataTy>(), "", "", "");
963 }
964 
965 template<typename dataTx, typename dataTy>
966 int gnuPlot::plot( const std::vector<dataTx> & x,
967  const std::vector<dataTy> & y,
968  const std::string & modifiers,
969  const std::string & title,
970  const std::string & name
971  )
972 {
973  return plot( x.data(), y.data(), x.size(), modifiers, title, name);
974 }
975 
976 template<typename dataTx, typename dataTy>
977 int gnuPlot::plot( const std::vector<dataTx> & x,
978  const std::vector<dataTy> & y,
979  const std::string & modifiers,
980  const std::string & name
981  )
982 {
983  return plot( x.data(), y.data(), x.size(), modifiers, "", name);
984 }
985 
986 template<typename dataTx, typename dataTy>
987 int gnuPlot::plot( const std::vector<dataTx> & x,
988  const std::vector<dataTy> & y,
989  const std::string & name
990  )
991 {
992  return plot( x.data(), y.data(), x.size(), "", "", name);
993 }
994 
995 template<typename dataTx, typename dataTy>
996 int gnuPlot::plot( const std::vector<dataTx> & x,
997  const std::vector<dataTy> & y
998  )
999 {
1000  return plot( x.data(), y.data(), x.size(), "", "", "");
1001 }
1002 
1003 template<typename dataTx, typename dataTy>
1004 int gnuPlot::point( dataTx x,
1005  dataTy y,
1006  const std::string & modifiers,
1007  const std::string & title
1008  )
1009 {
1010 
1011  return plot(&x, &y, 1, modifiers, title);
1012 }
1013 
1014 template<>
1015 std::string gpBinaryFormat<char>();
1016 
1017 template<>
1018 std::string gpBinaryFormat<unsigned char>();
1019 
1020 template<>
1021 std::string gpBinaryFormat<short>();
1022 
1023 template<>
1024 std::string gpBinaryFormat<unsigned short>();
1025 
1026 template<>
1027 std::string gpBinaryFormat<int>();
1028 
1029 template<>
1030 std::string gpBinaryFormat<unsigned int>();
1031 
1032 template<>
1033 std::string gpBinaryFormat<long>();
1034 
1035 template<>
1036 std::string gpBinaryFormat<unsigned long>();
1037 
1038 template<>
1039 std::string gpBinaryFormat<float>();
1040 
1041 template<>
1042 std::string gpBinaryFormat<double>();
1043 
1044 }//namespace math
1045 }//namespace mx
1046 
1047 
1048 #endif //math_plot_gnuPlot_hpp
1049 
An interactive c++ interface to gnuplot.
Definition: gnuPlot.hpp:193
int circle(double radius, const std::string &modifiers="", const std::string &title="", int npoints=10)
Draw a circle on the plot around the origin.
int doPlotCommand()
Issue the plot command for all the curves.
int plot(const std::string &fname)
Plot from a file without specifying the name or any modifiers.
std::string getResponse(const std::string &com, double timeout=0.5)
Get a response from gnuplot for a given command.
FILE * _pipeH
File stream for the gnuplot interface.
Definition: gnuPlot.hpp:203
int plot(const std::string &fname, const std::string &modifiers, const std::string &title, const std::string &name)
Plot from a file specifying all curve components.
bool _gpError
Set to true if the response indicates a gnuplot error.
Definition: gnuPlot.hpp:199
int xrange(double x0, double x1)
Set the x-axis range.
void title(const std::string &name, const std::string &title)
Modify the title for a curve.
int plot(const std::string &fname, const std::string &modifiers, const std::string &name)
Plot from a file without specifying the title.
int plotImpl(const void *x, const void *y, size_t Npts, size_t sizex, size_t sizey, const std::string &binaryx, const std::string &binaryy, const std::string &modifiers, const std::string &title, const std::string &name)
Implementation of 2-d binary plotting.
int plot(const std::string &fname, const std::string &name)
Plot from a file without modifiers.
void reset()
Clear all the curves and reset plot configuration.
int connect()
Connect to gnuplot.
int point(dataTx x, dataTy y, const std::string &modifiers="", const std::string &title="")
Plot a single point.
Definition: gnuPlot.hpp:1004
std::string _errFName
File name of the gnuplot stderr fifo.
Definition: gnuPlot.hpp:211
std::vector< std::string > _tempFiles
Vector of all temporary file names opened, used for removal on destruction.
Definition: gnuPlot.hpp:222
int ulogy()
Unset the y axis from log scale.
int plotImpl(const void *y, size_t Nbytes, const std::string &binary, const std::string &modifiers, const std::string &title, const std::string &name)
Implementation of 1-D binary plotting.
bool _deleteTemp
Flag to control whether temporary files are deleted on destruction. Default is true (files deleted).
Definition: gnuPlot.hpp:225
int logy()
Set the y axis to log scale.
int _errFD
File descriptor for the gnuplot stderr fifo.
Definition: gnuPlot.hpp:214
std::string _errLocation
Where to create gnuplot stderr fifo.
Definition: gnuPlot.hpp:208
int ulogxy()
Unset the x and y axes from log scale.
int replot()
Issue the replot command.
int logxy()
Set the x and y axes to log scale.
int yrange()
Unset the y-axis range.
void listCurves()
List the curves and their specifications.
int checkResponse(std::string &response, double timeout=0)
Check for a response from gnuplot.
bool gpError()
Return the value of the gpError flag.
void modifiers(const std::string &name, const std::string &modifiers)
Modify the modifiers for a curve.
int xrange()
Unset the x-axis range.
int ulogx()
Unset the x axis from log scale.
int yrange(double y0, double y1)
Set the y-axis range.
FILE * openTempFile(char *fname)
Open a temporary binary file, and provide the filename.
std::string _tempLocation
Location of temporary files.
Definition: gnuPlot.hpp:219
int circle(double xcen, double ycen, double radius, const std::string &modifiers="", const std::string &title="", int npoints=10)
Draw a circle on the plot.
int command(const std::string &com, bool flush=true)
Send a command to gnuplot.
int logx()
Set the x axis to log scale.
std::string gpErrorMsg()
Return the gnuplot error message.
void clear()
Clear all the curves.
The mxlib c++ namespace.
Definition: mxError.hpp:107