Line data Source code
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 "../../mxlib.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 : // Get the gnuplot binary format string for a type
89 : // Specializations below.
90 : template <typename dataT>
91 : std::string gpBinaryFormat()
92 : {
93 : static_assert( std::is_fundamental<dataT>::value || !std::is_fundamental<dataT>::value,
94 : "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 0 : gpCurve()
109 0 : {
110 0 : }
111 :
112 0 : gpCurve( const std::string &file, const std::string &title, const std::string &modifiers )
113 0 : : m_file( file ), m_title( title ), m_modifiers( modifiers )
114 : {
115 0 : }
116 :
117 : gpCurve( const std::string &file,
118 : const std::string &title,
119 : const std::string &modifiers,
120 : const std::string &binary )
121 : : m_file( file ), m_title( title ), m_modifiers( modifiers ), m_binary( binary )
122 : {
123 : }
124 :
125 0 : gpCurve( const gpCurve &gpc )
126 0 : {
127 0 : m_file = gpc.m_file;
128 0 : m_title = gpc.m_title;
129 0 : m_modifiers = gpc.m_modifiers;
130 0 : m_binary = gpc.m_binary;
131 0 : }
132 : };
133 :
134 : /// An interactive c++ interface to gnuplot
135 : /** Spawns a gnuplot sesssion and communicates with it.
136 : * \ingroup plotting
137 : *
138 : * \todo Use mxError for error reporting.
139 : *
140 : * An example of using gnuPlot to plot data from a file:
141 : * \code
142 : * gnuPlot gp; //This automatically connects, and is now ready to plot.
143 : *
144 : * gp.plot("my_data_file.dat", "u 1:2 w l"); //Plots the data in the file
145 : * \endcode
146 : *
147 : * Arrays can be plotted directly:
148 : * \code
149 : * std::vector<float> x;
150 : * std::vector<double> y;
151 : *
152 : * //...code to populate x and y
153 : *
154 : * gp.plot(x, y); //Plots y vs x.
155 : * \endcode
156 : * Note that the vector data types are different -- this is handled automatically.
157 : *
158 : * To get a response from the gnuplot session:
159 : * \code
160 : * std::cout << gp.getResponse("show terminal") << "\n"; //Sends the command to gnuplot, gets the response.
161 : * \endcode
162 : * Error checking and reporting is not straightforward since gnuplot does not return a result if there is no error. If
163 : * there is an error, it can take several hundred milliseconds for a response to be available. So for a typical plot
164 : * 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.
165 : *
166 : * For cases where a response is expected, the following example shows how to check for errors.
167 : * \code
168 : * errno = 0;
169 : * std::string response = gp.getResponse("show terminal"); //Waits up to 0.5 seconds, or a user specified timeout.
170 : *
171 : * if(response == "") //This indicates some error occurred, or a timeout.
172 : * {
173 : * if(gp.gpError())
174 : * {
175 : * std::cerr << "gnuplot returned error:\n" << gp.gpErrorMsg() << "\n";
176 : * }
177 : * else if(errno)
178 : * {
179 : * perror("error getting response: ");
180 : * }
181 : * else
182 : * {
183 : * std::cerr << "timed out\n";
184 : * }
185 : * }
186 : * else
187 : * {
188 : * std::cout << response << "\n";
189 : * }
190 : *
191 : * \endcode
192 : */
193 : class gnuPlot
194 : {
195 : typedef verbose::d verboseT;
196 : protected:
197 : int _connected{ 0 };
198 :
199 : /// Set to true if the response indicates a gnuplot error
200 : bool _gpError{ false };
201 : std::string _gpErrorMsg;
202 :
203 : /// File stream for the gnuplot interface
204 : FILE *_pipeH{ 0 };
205 :
206 : /// Where to create gnuplot stderr fifo
207 : /** Default is /dev/shm/
208 : */
209 : std::string _errLocation;
210 :
211 : /// File name of the gnuplot stderr fifo
212 : std::string _errFName;
213 :
214 : /// File descriptor for the gnuplot stderr fifo
215 : int _errFD{ 0 };
216 :
217 : /// Location of temporary files
218 : /** Default is /dev/shm/
219 : */
220 : std::string _tempLocation;
221 :
222 : /// Vector of all temporary file names opened, used for removal on destruction.
223 : std::vector<std::string> _tempFiles;
224 :
225 : /// Flag to control whether temporary files are deleted on destruction. Default is true (files deleted).
226 : bool _deleteTemp{ true };
227 :
228 : std::map<std::string, gpCurve> m_curveMap;
229 :
230 : public:
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
267 : ///< command is written
268 : );
269 :
270 : /// Check for a response from gnuplot.
271 : /** It typically takes some time for a response from gnuplot to become readable,
272 : * whether an error occurs or not. It is often 0.3 seconds or more. If there is no error, there will be no response
273 : * so waiting for a response to check for errors after every command can be very time consuming. Thus it is a
274 : * choice whether to check for errors from gnuplot after every command, and what timeout to use.
275 : *
276 : * \todo investigate having a second thread monitor for responses.
277 : *
278 : * gnuplot terminates all outputs with \c \\n\\n, so this reads up to these two characters. It then strips any
279 : * leading and trailing whitespace. If the response begins with \c gnuplot>, then the response is an error. In this
280 : * case, checkResponse returns -1 and the gpError flag is set. If gpError is not set but the return value is -1,
281 : * then some other error occurred (check \c errno).
282 : *
283 : * \retval 0 on timeout or successful read
284 : * \retval -1 on error, or if the gnuplot response indicates an error.
285 : */
286 : int checkResponse(
287 : std::string &response, ///< [out] contains the response from gnuplot, but is empty on timeout or error.
288 : double timeout = 0 ///< [in] [optional] the length of time, in seconds, to wait for a response. Default is 0,
289 : ///< but a minimum of 0.5 if a response is expected.
290 : );
291 :
292 : /// Get a response from gnuplot for a given command.
293 : /** This should only be used if a response is expected.
294 : *
295 : * \returns "" (empty string) on timeout or error (\c errno and gpError() should be checked), and the response from
296 : * gnuplot otherwise.
297 : */
298 : std::string getResponse( const std::string &com, ///< [in] the command string
299 : double timeout = 0.5 ///< [in] the length of time, in seconds, to wait for a response.
300 : ///< Default is 0.5, which is the minimum that should be used.
301 : );
302 :
303 : /// Issue the \b replot command
304 : /**
305 : * \retval 0 on success
306 : * \retval -1 on error
307 : */
308 : int replot();
309 :
310 : /// Set the x-axis range
311 : /** Sends the command:
312 : * \verbatim
313 : * set xrange [x0:x1]
314 : * \endverbatim
315 : *
316 : * \returns 0 on success
317 : * \returns -1 on error
318 : */
319 : int xrange( double x0, double x1 );
320 :
321 : /// Unset the x-axis range
322 : /** Sends the command:
323 : * \verbatim
324 : * unset xrange
325 : * \endverbatim
326 : *
327 : * \returns 0 on success
328 : * \returns -1 on error
329 : */
330 : int xrange();
331 :
332 : /// Set the y-axis range
333 : /** Sends the command:
334 : * \verbatim
335 : * set yrange [y0:y1]
336 : * \endverbatim
337 : *
338 : * \returns 0 on success
339 : * \returns -1 on error
340 : */
341 : int yrange( double y0, double y1 );
342 :
343 : /// Unset the y-axis range
344 : /** Sends the command:
345 : * \verbatim
346 : * unset yrange
347 : * \endverbatim
348 : *
349 : * \returns 0 on success
350 : * \returns -1 on error
351 : */
352 : int yrange();
353 :
354 : /// Set the y axis to log scale
355 : /** Sends the command:
356 : * \verbatim
357 : set log y
358 : \endverbatim
359 : *
360 : * \retval 0 on success
361 : * \retval -1 on error
362 : */
363 : int logy();
364 :
365 : /// Set the x axis to log scale
366 : /** Sends the command:
367 : * \verbatim
368 : set log x
369 : \endverbatim
370 : *
371 : * \retval 0 on success
372 : * \retval -1 on error
373 : */
374 : int logx();
375 :
376 : /// Set the x and y axes to log scale
377 : /** Sends the commands:
378 : * \verbatim
379 : set log x
380 : set log y
381 : \endverbatim
382 : *
383 : * \retval 0 on success
384 : * \retval -1 on error
385 : */
386 : int logxy();
387 :
388 : /// Unset the y axis from log scale
389 : /** Sends the command:
390 : * \verbatim
391 : unset log y
392 : \endverbatim
393 : *
394 : * \retval 0 on success
395 : * \retval -1 on error
396 : */
397 : int ulogy();
398 :
399 : /// Unset the x axis from log scale
400 : /** Sends the command:
401 : * \verbatim
402 : unset log x
403 : \endverbatim
404 : *
405 : * \retval 0 on success
406 : * \retval -1 on error
407 : */
408 : int ulogx();
409 :
410 : /// Unset the x and y axes from log scale
411 : /** Sends the command:
412 : * \verbatim
413 : unset log x
414 : unset log y
415 : \endverbatim
416 : *
417 : * \retval 0 on success
418 : * \retval -1 on error
419 : */
420 : int ulogxy();
421 :
422 : /// Plot from a file specifying all curve components.
423 : /** Forms the gnuplot plot command as follows:
424 : * \verbatim
425 : * plot '<fname>' <modifiers> t '<title>'
426 : * \endverbatim
427 : * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
428 : *
429 : * \retval 0 on success
430 : * \retval -1 on error
431 : */
432 : int plot( const std::string &fname, ///< [in] the name (with full path) of the file containing data to plot
433 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command.
434 : const std::string &title, ///< [in] the title for this curve
435 : const std::string &name ///< [in] the name for this curve. If "" then curve# is used.
436 : );
437 :
438 : /// Plot from a file without specifying the title
439 : /** Forms the gnuplot plot command as follows:
440 : * \verbatim
441 : * plot '<fname>' <modifiers> t ''
442 : * \endverbatim
443 : * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
444 : *
445 : * \retval 0 on success
446 : * \retval -1 on error
447 : *
448 : * \overload
449 : */
450 : int plot( const std::string &fname, ///< [in] the name (with full path) of the file containing data to plot
451 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command.
452 : const std::string &name ///< [in] the name for this curve. If "" then the curve# is used.
453 : );
454 :
455 : /// Plot from a file without modifiers
456 : /** The file name is used for the identifying name
457 : *
458 : * Forms the gnuplot plot command as follows:
459 : * \verbatim
460 : * plot '<fname>' <modifiers> t ''
461 : * \endverbatim
462 : * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
463 : *
464 : * \retval 0 on success
465 : * \retval -1 on error
466 : *
467 : * \overload
468 : */
469 : int plot( const std::string &fname, ///< [in] the name (with full path) of the file containing data to plot
470 : const std::string &name ///< [in] the name for this curve. If "" then the curve# is used
471 : );
472 :
473 : /// Plot from a file without specifying the name or any modifiers
474 : /** The file name is used for the identifying name
475 : *
476 : * Forms the gnuplot plot command as follows:
477 : * \verbatim
478 : * plot '<fname>' t ''
479 : * \endverbatim
480 : * The modifiers string can contain any modifiers such as \a using, etc. Should generally not include \a title.
481 : *
482 : * \retval 0 on success
483 : * \retval -1 on error
484 : *
485 : * \overload
486 : */
487 : int plot( const std::string &fname /**< [in] the name (with full path) of the file containing data to plot */ );
488 :
489 : /// Plot data from an array
490 : /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
491 : * \verbatim
492 : * plot "temp-file-name" binary format="%dataT" u 1 t "title" <modifiers>
493 : * \endverbatim
494 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
495 : * can contain any other modifiers. Title is specified so that the name of the temporary file name is not printed
496 : * on the plot.
497 : *
498 : * \retval 0 on success
499 : * \retval -1 on error
500 : */
501 : template <typename dataT>
502 : int plot( const dataT *y, ///< [in] a pointer to an array of data
503 : size_t N, ///< [in] the length of the array
504 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
505 : ///< \b format, \b using, and \b title.
506 : const std::string &
507 : title, ///< [in] contains the title of the data set, default is an empty string and no key on the plot
508 : const std::string &name ///< [in] the identifying name of this curve
509 : );
510 :
511 : /// Plot data from an array
512 : /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
513 : * \verbatim
514 : * plot "temp-file-name" binary format="%dataT" u 1 t '' <modifiers>
515 : * \endverbatim
516 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
517 : * can contain any other modifiers. Title is specified so that the name of the temporary file name is not printed
518 : * on the plot.
519 : *
520 : * \retval 0 on success
521 : * \retval -1 on error
522 : */
523 : template <typename dataT>
524 : int plot( const dataT *y, ///< [in] a pointer to an array of data
525 : size_t N, ///< [in] the length of the array
526 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
527 : ///< \b format, \b using, and \b title.
528 : const std::string &name ///< [in] the identifying name of this curve
529 : );
530 :
531 : /// Plot data from an array
532 : /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
533 : * \verbatim
534 : * plot "temp-file-name" binary format="%dataT" u 1 t '' <modifiers>
535 : * \endverbatim
536 : *
537 : *
538 : * \retval 0 on success
539 : * \retval -1 on error
540 : */
541 : template <typename dataT>
542 : int plot( const dataT *y, ///< [in] a pointer to an array of data
543 : size_t N, ///< [in] the length of the array
544 : const std::string &name ///< [in] the identifying name of this curve
545 : );
546 :
547 : /// Plot data from an array
548 : /** Copies the data in the array to a temporary binary file, and then forms the gnuplot plot command as follows:
549 : * \verbatim
550 : * plot "temp-file-name" binary format="%dataT" u 1 t ''
551 : * \endverbatim
552 : *
553 : * \retval 0 on success
554 : * \retval -1 on error
555 : */
556 : template <typename dataT>
557 : int plot( const dataT *y, ///< [in] a pointer to an array of data
558 : size_t N ///< [in] the length of the array
559 : );
560 :
561 : /// Plot data from a vector
562 : /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
563 : * \verbatim
564 : * plot "temp-file-name" binary format="%dataT" u 1 t "title" <modifiers>
565 : * \endverbatim
566 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
567 : * can contain any other modifiers. Title is specified so that the name of the temporary file name is not printed
568 : * on the plot.
569 : *
570 : * \retval 0 on success
571 : * \retval -1 on error
572 : */
573 : template <typename dataT>
574 : int plot( const std::vector<dataT> &y, ///< [in] the vector containing the data
575 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
576 : ///< \b format, \b using, and \b title.
577 : const std::string &
578 : title, ///< [in] contains the title of the data set, default is an empty string and no key on the plot
579 : const std::string &name ///< [in] the identifying name of this curve
580 : );
581 :
582 : /// Plot data from a vector
583 : /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
584 : * \verbatim
585 : * plot "temp-file-name" binary format="%dataT" u 1 t '' <modifiers>
586 : * \endverbatim
587 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
588 : * can contain any other modifiers. Title is specified so that the name of the temporary file name is not printed
589 : * on the plot.
590 : *
591 : * \retval 0 on success
592 : * \retval -1 on error
593 : */
594 : template <typename dataT>
595 : int plot( const std::vector<dataT> &y, ///< [in] the vector containing the data
596 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
597 : ///< \b format, \b using, and \b title.
598 : const std::string &name ///< [in] the identifying name of this curve
599 : );
600 :
601 : /// Plot data from a vector
602 : /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
603 : * \verbatim
604 : * plot "temp-file-name" binary format="%dataT" u 1 t ''
605 : * \endverbatim
606 : *
607 : * \retval 0 on success
608 : * \retval -1 on error
609 : */
610 : template <typename dataT>
611 : int plot( const std::vector<dataT> &y, ///< [in] the vector containing the data
612 : const std::string &name ///< [in] the identifying name of this curve
613 : );
614 :
615 : /// Plot data from a vector
616 : /** Copies the data in the vector to a temporary binary file, and then forms the gnuplot plot command as follows:
617 : * \verbatim
618 : * plot "temp-file-name" binary format="%dataT" u 1 t ''
619 : * \endverbatim
620 : *
621 : * \retval 0 on success
622 : * \retval -1 on error
623 : */
624 : template <typename dataT>
625 : int plot( const std::vector<dataT> &y /**< [in] the vector containing the data*/ );
626 :
627 : /// Plot y vs. x data from arrays
628 : /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
629 : * \verbatim
630 : plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t "title" <modifiers>
631 : \endverbatim
632 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
633 : can contain any other modifiers. Title is
634 : * specified so that the name of the temporary file name is not printed on the plot.
635 : *
636 : * \retval 0 on success
637 : * \retval -1 on error
638 : */
639 : template <typename dataTx, typename dataTy>
640 : int plot( const dataTx *x, ///< [in] a pointer to an array of data for the independent variable
641 : const dataTy *y, ///< [in] a pointer to an array of data for the dependent variable
642 : size_t N, ///< [in] the length of the arrays
643 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
644 : ///< \b format, \b using, and \b title.
645 : const std::string &title, ///< [in] contains the title of the data set
646 : const std::string &name ///< [in] the identifying name of the curve
647 : );
648 :
649 : /// Plot y vs. x data from arrays
650 : /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
651 : * \verbatim
652 : * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t '' <modifiers>
653 : * \endverbatim
654 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
655 : * can contain any other modifiers. Title is specified so that the name of the temporary file name is not printed
656 : * on the plot.
657 : *
658 : * \retval 0 on success
659 : * \retval -1 on error
660 : */
661 : template <typename dataTx, typename dataTy>
662 : int plot( const dataTx *x, ///< [in] a pointer to an array of data for the independent variable
663 : const dataTy *y, ///< [in] a pointer to an array of data for the dependent variable
664 : size_t N, ///< [in] the length of the arrays
665 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
666 : ///< \b format, \b using, and \b title.
667 : const std::string &name ///< [in] the identifying name of the curve
668 : );
669 :
670 : /// Plot y vs. x data from arrays
671 : /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
672 : * \verbatim
673 : * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
674 : * \endverbatim
675 : *
676 : * \retval 0 on success
677 : * \retval -1 on error
678 : */
679 : template <typename dataTx, typename dataTy>
680 : int plot( const dataTx *x, ///< [in] a pointer to an array of data for the independent variable
681 : const dataTy *y, ///< [in] a pointer to an array of data for the dependent variable
682 : size_t N, ///< [in] the length of the arrays
683 : const std::string &name ///< [in] the identifying name of the curve
684 : );
685 :
686 : /// Plot y vs. x data from arrays
687 : /** Copies the data in the arrays to a temporary binary file, and then forms the gnuplot plot command as follows:
688 : * \verbatim
689 : * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
690 : * \endverbatim
691 : *
692 : * \retval 0 on success
693 : * \retval -1 on error
694 : */
695 : template <typename dataTx, typename dataTy>
696 : int plot( const dataTx *x, ///< [in] a pointer to an array of data for the independent variable
697 : const dataTy *y, ///< [in] a pointer to an array of data for the dependent variable
698 : size_t N ///< [in] the length of the arrays
699 : );
700 :
701 : /// Plot y vs. x data from vectors
702 : /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
703 : * \verbatim
704 : plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t "title" <modifiers>
705 : \endverbatim
706 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
707 : can contain any other modifiers. Title is
708 : * specified so that the name of the temporary file name is not printed on the plot.
709 : *
710 : * \retval 0 on success
711 : * \retval -1 on error
712 : */
713 : template <typename dataTx, typename dataTy>
714 : int plot( const std::vector<dataTx> &x, ///< [in] a vector of data for the independent variable
715 : const std::vector<dataTy> &y, ///< [in] a vector of data for the dependent variable
716 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
717 : ///< \b format, \b using, and \b title.
718 : const std::string &title, ///< [in] contains the title of the data set
719 : const std::string &name ///< [in] the identifying name of the curve
720 : );
721 :
722 : /// Plot y vs. x data from vectors
723 : /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
724 : * \verbatim
725 : plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t '' <modifiers>
726 : \endverbatim
727 : * The modifiers string \b must \b NOT contain the \b binary, \b format, \b using, or the \b title modifiers, but
728 : can contain any other modifiers. Title is
729 : * specified so that the name of the temporary file name is not printed on the plot.
730 : *
731 : * \retval 0 on success
732 : * \retval -1 on error
733 : */
734 : template <typename dataTx, typename dataTy>
735 : int plot( const std::vector<dataTx> &x, ///< [in] a vector of data for the independent variable
736 : const std::vector<dataTy> &y, ///< [in] a vector of data for the dependent variable
737 : const std::string &modifiers, ///< [in] contains any modifiers to the plot command other than \b binary,
738 : ///< \b format, \b using, and \b title.
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 : const std::string &name ///< [in] the identifying name of the curve
755 : );
756 :
757 : /// Plot y vs. x data from vectors
758 : /** Copies the data in the vectors to a temporary binary file, and then forms the gnuplot plot command as follows:
759 : * \verbatim
760 : * plot "temp-file-name" binary format="%dataTx%dataTy" u 1:2 t ''
761 : * \endverbatim
762 : *
763 : * \retval 0 on success
764 : * \retval -1 on error
765 : */
766 : template <typename dataTx, typename dataTy>
767 : int plot( const std::vector<dataTx> &x, ///< [in] a vector of data for the independent variable
768 : const std::vector<dataTy> &y ///< [in] a vector of data for the dependent variable
769 : );
770 :
771 : /// Plot a single point
772 : /** Copies the position as a length-1 vector to a temporary binary file, and then plots it.
773 : *
774 : *
775 : * \retval 0 on success
776 : * \retval -1 on error
777 : */
778 : template <typename dataTx, typename dataTy>
779 : int point( dataTx x, ///< [in] the independent axis (x) coordinate of the point
780 : dataTy y, ///< [in] the dependent axis (y) coordinate of the point
781 : const std::string &modifiers = "", ///< [in] [optional] contains any modifiers to the plot command other
782 : ///< than \b binary, \b format, \b using, and \b title.
783 : const std::string &title = "" ///< [in] [optional] contains the title of the data set, default is an
784 : ///< empty string and no key on the plot
785 : );
786 :
787 : /// Draw a circle on the plot
788 : /** Creates a circle with specified center and radius, and plots it.
789 : */
790 : int circle( double xcen, ///< [in] the x-coordinate of the circle center
791 : double ycen, ///< [in] the y-coordinate of the circle center
792 : double radius, ///< [in] the circle radius
793 : const std::string &modifiers = "", ///< [in] [optional] contains any modifiers to the plot command other
794 : ///< than \b binary, \b format, \b using, and \b title.
795 : const std::string &title = "", ///< [in] [optional] contains the title of the data set, default is an
796 : ///< empty string and no key on the plot
797 : int npoints = 10 ///< [in] [optional] specifies the number of points in each half circle. Default 10 is
798 : ///< usually sufficient.
799 : );
800 :
801 : /// Draw a circle on the plot around the origin
802 : /** Creates a circle with radius and center (0,0), and plots it.
803 : */
804 : int circle( double radius, ///< [in] the circle radius
805 : const std::string &modifiers = "", ///< [in] [optional] contains any modifiers to the plot command other
806 : ///< than \b binary, \b format, \b using, and \b title.
807 : const std::string &title = "", ///< [in] [optional] contains the title of the data set, default is an
808 : ///< empty string and no key on the plot
809 : int npoints = 10 ///< [in] [optional] specifies the number of points in each half circle. Default 10 is
810 : ///< usually sufficient.
811 : );
812 :
813 : /// Clear all the curves
814 : void clear();
815 :
816 : /// Clear all the curves and reset plot configuration
817 : void reset();
818 :
819 : /// List the curves and their specifications.
820 : void listCurves();
821 :
822 : /// Modify the modifiers for a curve
823 : void modifiers( const std::string &name, ///< [in] the name of the curve
824 : const std::string &modifiers ///< [in] the new modifiers
825 : );
826 :
827 : /// Modify the title for a curve
828 : void title( const std::string &name, ///< [in] the name of the curve
829 : const std::string &title ///< [in] the new title
830 : );
831 :
832 : protected:
833 : /// Implementation of 1-D binary plotting.
834 : int plotImpl( const void *y,
835 : size_t Nbytes,
836 : const std::string &binary,
837 : const std::string &modifiers,
838 : const std::string &title,
839 : const std::string &name );
840 :
841 : /// Implementation of 2-d binary plotting.
842 : int plotImpl( const void *x,
843 : const void *y,
844 : size_t Npts,
845 : size_t sizex,
846 : size_t sizey,
847 : const std::string &binaryx,
848 : const std::string &binaryy,
849 : const std::string &modifiers,
850 : const std::string &title,
851 : const std::string &name );
852 :
853 : /// Issue the plot command for all the curves
854 : int doPlotCommand();
855 :
856 : /// Open a temporary binary file, and provide the filename.
857 : FILE *openTempFile( char *fname );
858 :
859 : private:
860 : /// Initialize an instance, only used at construction
861 : void init();
862 : };
863 :
864 : template <typename dataT>
865 : int gnuPlot::plot(
866 : const dataT *y, size_t N, const std::string &modifiers, const std::string &title, const std::string &name )
867 : {
868 : return plotImpl( y, N * sizeof( dataT ), gpBinaryFormat<dataT>(), modifiers, title, name );
869 : }
870 :
871 : template <typename dataT>
872 0 : int gnuPlot::plot( const dataT *y, size_t N, const std::string &modifiers, const std::string &name )
873 : {
874 0 : return plotImpl( y, N * sizeof( dataT ), gpBinaryFormat<dataT>(), modifiers, "", name );
875 : }
876 :
877 : template <typename dataT>
878 : int gnuPlot::plot( const dataT *y, size_t N, const std::string &name )
879 : {
880 : return plotImpl( y, N * sizeof( dataT ), gpBinaryFormat<dataT>(), "", "", name );
881 : }
882 :
883 : template <typename dataT>
884 : int gnuPlot::plot( const dataT *y, size_t N )
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 : return plot<dataT>( y.data(), y.size(), modifiers, title, name );
896 : }
897 :
898 : template <typename dataT>
899 : int gnuPlot::plot( const std::vector<dataT> &y, const std::string &modifiers, const std::string &name )
900 : {
901 : return plot<dataT>( y.data(), y.size(), modifiers, "", name );
902 : }
903 :
904 : template <typename dataT>
905 : int gnuPlot::plot( const std::vector<dataT> &y, const std::string &name )
906 : {
907 : return plot<dataT>( y.data(), y.size(), "", "", name );
908 : }
909 :
910 : template <typename dataT>
911 : int gnuPlot::plot( const std::vector<dataT> &y )
912 : {
913 : return plot<dataT>( y.data(), y.size(), "", "", "" );
914 : }
915 :
916 : template <typename dataTx, typename dataTy>
917 0 : int gnuPlot::plot( const dataTx *x,
918 : const dataTy *y,
919 : size_t N,
920 : const std::string &modifiers,
921 : const std::string &title,
922 : const std::string &name )
923 : {
924 0 : return plotImpl( x,
925 : y,
926 : N,
927 : sizeof( dataTx ),
928 : sizeof( dataTy ),
929 0 : gpBinaryFormat<dataTx>(),
930 0 : gpBinaryFormat<dataTy>(),
931 : modifiers,
932 : title,
933 0 : name );
934 : }
935 :
936 : template <typename dataTx, typename dataTy>
937 : int gnuPlot::plot( const dataTx *x, const dataTy *y, size_t N, const std::string &modifiers, const std::string &name )
938 : {
939 : return plotImpl( x,
940 : y,
941 : N,
942 : sizeof( dataTx ),
943 : sizeof( dataTy ),
944 : gpBinaryFormat<dataTx>(),
945 : gpBinaryFormat<dataTy>(),
946 : modifiers,
947 : "",
948 : name );
949 : }
950 :
951 : template <typename dataTx, typename dataTy>
952 : int gnuPlot::plot( const dataTx *x, const dataTy *y, size_t N, const std::string &name )
953 : {
954 : return plotImpl(
955 : x, y, N, sizeof( dataTx ), sizeof( dataTy ), gpBinaryFormat<dataTx>(), gpBinaryFormat<dataTy>(), "", "", name );
956 : }
957 :
958 : template <typename dataTx, typename dataTy>
959 : int gnuPlot::plot( const dataTx *x, const dataTy *y, size_t N )
960 : {
961 : return plotImpl(
962 : 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 : return plot( x.data(), y.data(), x.size(), modifiers, title, name );
973 : }
974 :
975 : template <typename dataTx, typename dataTy>
976 0 : int gnuPlot::plot( const std::vector<dataTx> &x,
977 : const std::vector<dataTy> &y,
978 : const std::string &modifiers,
979 : const std::string &name )
980 : {
981 0 : return plot( x.data(), y.data(), x.size(), modifiers, "", name );
982 : }
983 :
984 : template <typename dataTx, typename dataTy>
985 : int gnuPlot::plot( const std::vector<dataTx> &x, const std::vector<dataTy> &y, const std::string &name )
986 : {
987 : return plot( x.data(), y.data(), x.size(), "", "", name );
988 : }
989 :
990 : template <typename dataTx, typename dataTy>
991 : int gnuPlot::plot( const std::vector<dataTx> &x, const std::vector<dataTy> &y )
992 : {
993 : return plot( x.data(), y.data(), x.size(), "", "", "" );
994 : }
995 :
996 : template <typename dataTx, typename dataTy>
997 : int gnuPlot::point( dataTx x, dataTy y, const std::string &modifiers, const std::string &title )
998 : {
999 :
1000 : return plot( &x, &y, 1, modifiers, title );
1001 : }
1002 :
1003 : template <>
1004 : std::string gpBinaryFormat<char>();
1005 :
1006 : template <>
1007 : std::string gpBinaryFormat<unsigned char>();
1008 :
1009 : template <>
1010 : std::string gpBinaryFormat<short>();
1011 :
1012 : template <>
1013 : std::string gpBinaryFormat<unsigned short>();
1014 :
1015 : template <>
1016 : std::string gpBinaryFormat<int>();
1017 :
1018 : template <>
1019 : std::string gpBinaryFormat<unsigned int>();
1020 :
1021 : template <>
1022 : std::string gpBinaryFormat<long>();
1023 :
1024 : template <>
1025 : std::string gpBinaryFormat<unsigned long>();
1026 :
1027 : template <>
1028 : std::string gpBinaryFormat<float>();
1029 :
1030 : template <>
1031 : std::string gpBinaryFormat<double>();
1032 :
1033 : } // namespace math
1034 : } // namespace mx
1035 :
1036 : #endif // math_plot_gnuPlot_hpp
|