Advertisement
Guest User

gnuplot_i.hpp

a guest
Nov 22nd, 2013
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 59.94 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////////////////////
  2. ///
  3. ///  \brief A C++ interface to gnuplot.
  4. ///
  5. ///
  6. ///  The interface uses pipes and so won't run on a system that doesn't have
  7. ///  POSIX pipe support Tested on Windows (MinGW and Visual C++) and Linux (GCC)
  8. ///
  9. /// Version history:
  10. /// 0. C interface
  11. ///    by N. Devillard (27/01/03)
  12. /// 1. C++ interface: direct translation from the C interface
  13. ///    by Rajarshi Guha (07/03/03)
  14. /// 2. corrections for Win32 compatibility
  15. ///    by V. Chyzhdzenka (20/05/03)
  16. /// 3. some member functions added, corrections for Win32 and Linux
  17. ///    compatibility
  18. ///    by M. Burgis (10/03/08)
  19. ///
  20. /// Requirements:
  21. /// * gnuplot has to be installed (http://www.gnuplot.info/download.html)
  22. /// * for Windows: set Path-Variable for Gnuplot path
  23. ///         (e.g. C:/program files/gnuplot/bin)
  24. ///         or set Gnuplot path with:
  25. ///         Gnuplot::set_GNUPlotPath(const std::string &path);
  26. ///
  27. ////////////////////////////////////////////////////////////////////////////////
  28.  
  29.  
  30. #ifndef _GNUPLOT_PIPES_H_
  31. #define _GNUPLOT_PIPES_H_
  32.  
  33.  
  34. #include <iostream>
  35. #include <string>
  36. #include <vector>
  37. #include <fstream>  
  38. #include <sstream>              // for std::ostringstream
  39. #include <stdexcept>
  40. #include <cstdio>    
  41. #include <cstdlib>              // for getenv()
  42. #include <list>                 // for std::list
  43.  
  44.  
  45. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  46. //defined for 32 and 64-bit environments
  47.  #include <io.h>                // for _access(), _mktemp()
  48.  #define GP_MAX_TMP_FILES  27   // 27 temporary files it's Microsoft restriction
  49. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  50. //all UNIX-like OSs (Linux, *BSD, MacOSX, Solaris, ...)
  51.  #include <unistd.h>            // for access(), mkstemp()
  52.  #define GP_MAX_TMP_FILES  64
  53. #else
  54.  #error unsupported or unknown operating system
  55. #endif
  56.  
  57. //declare classes in global namespace
  58.  
  59.  
  60. class GnuplotException : public std::runtime_error
  61. {
  62.     public:
  63.         GnuplotException(const std::string &msg) : std::runtime_error(msg){}
  64. };
  65.  
  66.  
  67.  
  68. class Gnuplot
  69. {
  70.     private:
  71.  
  72.     //----------------------------------------------------------------------------------
  73.     // member data
  74.     ///\brief pointer to the stream that can be used to write to the pipe
  75.         FILE                    *gnucmd;
  76.     ///\brief validation of gnuplot session      
  77.         bool                     valid;  
  78.     ///\brief true = 2d, false = 3d      
  79.         bool                     two_dim;  
  80.     ///\brief number of plots in session  
  81.         int                      nplots;  
  82.     ///\brief functions and data are displayed in a defined styles  
  83.         std::string              pstyle;  
  84.     ///\brief interpolate and approximate data in defined styles (e.g. spline)
  85.         std::string              smooth;    
  86.     ///\brief list of created tmpfiles  
  87.         std::vector<std::string> tmpfile_list;
  88.  
  89.     //----------------------------------------------------------------------------------
  90.     // static data
  91.     ///\brief number of all tmpfiles (number of tmpfiles restricted)
  92.         static int               tmpfile_num;  
  93.     ///\brief name of executed GNUPlot file    
  94.         static std::string       m_sGNUPlotFileName;
  95.     ///\brief gnuplot path
  96.         static std::string       m_sGNUPlotPath;
  97.     ///\brief standart terminal, used by showonscreen    
  98.         static std::string       terminal_std;      
  99.  
  100.     //----------------------------------------------------------------------------------
  101.     // member functions (auxiliary functions)
  102.     // ---------------------------------------------------
  103.     ///\brief get_program_path(); and popen();
  104.     ///
  105.     /// \param --> void
  106.     ///
  107.     /// \return <-- void
  108.     // ---------------------------------------------------
  109.         void           init();
  110.     // ---------------------------------------------------
  111.     ///\brief creates tmpfile and returns its name  
  112.     ///
  113.     /// \param tmp --> points to the tempfile
  114.     ///
  115.     /// \return <-- the name of the tempfile
  116.     // ---------------------------------------------------                          
  117.         std::string    create_tmpfile(std::ofstream &tmp);  
  118.  
  119.     //----------------------------------------------------------------------------------
  120.     ///\brief gnuplot path found?
  121.     ///
  122.     /// \param ---
  123.     ///
  124.     /// \return <-- found the gnuplot path (yes == true, no == false)
  125.     // ---------------------------------------------------------------------------------
  126.     static bool    get_program_path();
  127.    
  128.     // ---------------------------------------------------------------------------------
  129.     ///\brief checks if file is available
  130.     ///
  131.     /// \param filename --> the filename
  132.     /// \param mode     --> the mode [optional,default value = 0]
  133.     ///
  134.     /// \return file exists (yes == true, no == false)
  135.     // ---------------------------------------------------------------------------------                                  
  136.     bool file_available(const std::string &filename);
  137.      
  138.     // ---------------------------------------------------------------------------------
  139.     ///\brief checks if file exists
  140.     ///
  141.     /// \param filename --> the filename
  142.     /// \param mode     --> the mode [optional,default value = 0]
  143.     ///
  144.     /// \return file exists (yes == true, no == false)
  145.     // ---------------------------------------------------------------------------------                                  
  146.     static bool    file_exists(const std::string &filename, int mode=0);
  147.  
  148.     public:
  149.  
  150.         // ----------------------------------------------------------------------------
  151.         /// \brief optional function: set Gnuplot path manual
  152.         /// attention:  for windows: path with slash '/' not backslash '\'
  153.         ///
  154.         /// \param path --> the gnuplot path
  155.         ///
  156.         /// \return true on success, false otherwise
  157.         // ----------------------------------------------------------------------------
  158.         static bool set_GNUPlotPath(const std::string &path);
  159.  
  160.  
  161.         // ----------------------------------------------------------------------------
  162.         /// optional: set standard terminal, used by showonscreen
  163.         ///   defaults: Windows - win, Linux - x11, Mac - aqua
  164.         ///
  165.         /// \param type --> the terminal type
  166.         ///
  167.         /// \return ---
  168.         // ----------------------------------------------------------------------------
  169.         static void set_terminal_std(const std::string &type);
  170.  
  171.         //-----------------------------------------------------------------------------
  172.         // constructors
  173.         // ----------------------------------------------------------------------------
  174.  
  175.  
  176.         ///\brief set a style during construction
  177.         Gnuplot(const std::string &style = "points");
  178.  
  179.         /// plot a single std::vector at one go
  180.         Gnuplot(const std::vector<double> &x,
  181.                 const std::string &title = "",
  182.                 const std::string &style = "points",
  183.                 const std::string &labelx = "x",
  184.                 const std::string &labely = "y");
  185.  
  186.          /// plot pairs std::vector at one go
  187.         Gnuplot(const std::vector<double> &x,
  188.                 const std::vector<double> &y,
  189.                 const std::string &title = "",
  190.                 const std::string &style = "points",
  191.                 const std::string &labelx = "x",
  192.                 const std::string &labely = "y");
  193.  
  194.          /// plot triples std::vector at one go
  195.         Gnuplot(const std::vector<double> &x,
  196.                 const std::vector<double> &y,
  197.                 const std::vector<double> &z,
  198.                 const std::string &title = "",
  199.                 const std::string &style = "points",
  200.                 const std::string &labelx = "x",
  201.                 const std::string &labely = "y",
  202.                 const std::string &labelz = "z");
  203.  
  204.          /// destructor: needed to delete temporary files
  205.         ~Gnuplot();
  206.  
  207.  
  208.     //----------------------------------------------------------------------------------
  209.  
  210.     /// send a command to gnuplot
  211.         Gnuplot& cmd(const std::string &cmdstr);
  212.     // ---------------------------------------------------------------------------------
  213.     ///\brief Sends a command to an active gnuplot session, identical to cmd()
  214.     /// send a command to gnuplot using the <<  operator
  215.     ///
  216.     /// \param cmdstr --> the command string
  217.     ///
  218.     /// \return <-- a reference to the gnuplot object  
  219.     // ---------------------------------------------------------------------------------
  220.     inline Gnuplot& operator<<(const std::string &cmdstr){
  221.         cmd(cmdstr);
  222.         return(*this);
  223.     }
  224.  
  225.  
  226.  
  227.     //----------------------------------------------------------------------------------
  228.     // show on screen or write to file
  229.  
  230.     /// sets terminal type to terminal_std
  231.     Gnuplot& showonscreen(); // window output is set by default (win/x11/aqua)
  232.  
  233.     /// saves a gnuplot session to a postscript file, filename without extension
  234.     Gnuplot& savetops(const std::string &filename = "gnuplot_output");
  235.  
  236.  
  237.     //----------------------------------------------------------------------------------
  238.     // set and unset
  239.  
  240.     /// set line style (some of these styles require additional information):
  241.     ///  lines, points, linespoints, impulses, dots, steps, fsteps, histeps,
  242.     ///  boxes, histograms, filledcurves
  243.     Gnuplot& set_style(const std::string &stylestr = "points");
  244.  
  245.     /// interpolation and approximation of data, arguments:
  246.     ///  csplines, bezier, acsplines (for data values > 0), sbezier, unique, frequency
  247.     /// (works only with plot_x, plot_xy, plotfile_x, plotfile_xy
  248.     /// (if smooth is set, set_style has no effekt on data plotting)
  249.     Gnuplot& set_smooth(const std::string &stylestr = "csplines");
  250.  
  251.     // ----------------------------------------------------------------------
  252.     /// \brief unset smooth
  253.     /// attention: smooth is not set by default
  254.     ///
  255.     /// \param ---
  256.     ///
  257.     /// \return <-- a reference to a gnuplot object
  258.     // ----------------------------------------------------------------------
  259.     inline Gnuplot& unset_smooth(){ smooth = ""; return *this;};
  260.  
  261.  
  262.     /// scales the size of the points used in plots
  263.     Gnuplot& set_pointsize(const double pointsize = 1.0);
  264.  
  265.     /// turns grid on/off
  266.     inline Gnuplot& set_grid()  {cmd("set grid");return *this;};
  267.     /// grid is not set by default 
  268.     inline Gnuplot& unset_grid(){cmd("unset grid");return *this;};
  269.  
  270.     // -----------------------------------------------
  271.     /// set the mulitplot mode
  272.     ///
  273.     /// \param ---
  274.     ///
  275.     /// \return <-- reference to the gnuplot object
  276.     // -----------------------------------------------
  277.     inline Gnuplot& set_multiplot(){cmd("set multiplot") ;return *this;};
  278.  
  279.     // -----------------------------------------------
  280.     /// unsets the mulitplot mode
  281.     ///
  282.     /// \param ---
  283.     ///
  284.     /// \return <-- reference to the gnuplot object
  285.     // -----------------------------------------------
  286.     inline Gnuplot& unset_multiplot(){cmd("unset multiplot");return *this;};
  287.    
  288.  
  289.  
  290.     /// set sampling rate of functions, or for interpolating data
  291.     Gnuplot& set_samples(const int samples = 100);
  292.     /// set isoline density (grid) for plotting functions as surfaces (for 3d plots)
  293.     Gnuplot& set_isosamples(const int isolines = 10);
  294.  
  295.     // --------------------------------------------------------------------------
  296.     /// enables/disables hidden line removal for surface plotting (for 3d plot)
  297.     ///
  298.     /// \param ---
  299.     ///
  300.     /// \return <-- reference to the gnuplot object
  301.     // --------------------------------------------------------------------------
  302.     Gnuplot& set_hidden3d(){cmd("set hidden3d");return *this;};
  303.  
  304.     // ---------------------------------------------------------------------------
  305.     /// hidden3d is not set by default
  306.     ///
  307.     /// \param ---
  308.     ///
  309.     /// \return <-- reference to the gnuplot object
  310.     // ---------------------------------------------------------------------------
  311.     inline Gnuplot& unset_hidden3d(){cmd("unset hidden3d"); return *this;};
  312.  
  313.     /// enables/disables contour drawing for surfaces (for 3d plot)
  314.     ///  base, surface, both
  315.     Gnuplot& set_contour(const std::string &position = "base");
  316.     // --------------------------------------------------------------------------
  317.     /// contour is not set by default, it disables contour drawing for surfaces
  318.     ///
  319.     /// \param ---
  320.     ///
  321.     /// \return <-- reference to the gnuplot object
  322.     // ------------------------------------------------------------------
  323.     inline Gnuplot& unset_contour(){cmd("unset contour");return *this;};
  324.  
  325.     // ------------------------------------------------------------
  326.     /// enables/disables the display of surfaces (for 3d plot)
  327.     ///
  328.     /// \param --- 
  329.     ///
  330.     /// \return <-- reference to the gnuplot object
  331.     // ------------------------------------------------------------------
  332.     inline Gnuplot& set_surface(){cmd("set surface");return *this;};
  333.  
  334.     // ----------------------------------------------------------
  335.     /// surface is set by default,
  336.     /// it disables the display of surfaces (for 3d plot)
  337.     ///
  338.     /// \param --- 
  339.     ///
  340.     /// \return <-- reference to the gnuplot object
  341.     // ------------------------------------------------------------------
  342.     inline Gnuplot& unset_surface(){cmd("unset surface"); return *this;}
  343.  
  344.  
  345.     /// switches legend on/off
  346.     /// position: inside/outside, left/center/right, top/center/bottom, nobox/box
  347.     Gnuplot& set_legend(const std::string &position = "default");
  348.  
  349.     // ------------------------------------------------------------------
  350.     /// \brief  Switches legend off
  351.     /// attention:legend is set by default
  352.     ///
  353.     /// \param --- 
  354.     ///
  355.     /// \return <-- reference to the gnuplot object
  356.     // ------------------------------------------------------------------
  357.     inline Gnuplot& unset_legend(){cmd("unset key"); return *this;}
  358.  
  359.     // -----------------------------------------------------------------------
  360.     /// \brief sets and clears the title of a gnuplot session
  361.     ///
  362.     /// \param title --> the title of the plot [optional, default == ""]
  363.     ///
  364.     /// \return <-- reference to the gnuplot object
  365.     // -----------------------------------------------------------------------
  366.     inline Gnuplot& set_title(const std::string &title = "")
  367.     {
  368.         std::string cmdstr;
  369.         cmdstr = "set title \"";
  370.         cmdstr+=title;
  371.         cmdstr+="\"";
  372.         *this<<cmdstr;
  373.         return *this;
  374.     }
  375.  
  376.     //----------------------------------------------------------------------------------
  377.     ///\brief Clears the title of a gnuplot session
  378.     /// The title is not set by default.
  379.     ///
  380.     /// \param ---
  381.     ///
  382.     /// \return <-- reference to the gnuplot object
  383.     // ---------------------------------------------------------------------------------
  384.     inline Gnuplot& unset_title(){this->set_title();return *this;}
  385.  
  386.  
  387.     /// set x axis label
  388.     Gnuplot& set_ylabel(const std::string &label = "x");
  389.     /// set y axis label
  390.     Gnuplot& set_xlabel(const std::string &label = "y");
  391.     /// set z axis label
  392.     Gnuplot& set_zlabel(const std::string &label = "z");
  393.  
  394.     /// set axis - ranges
  395.     Gnuplot& set_xrange(const double iFrom,
  396.                         const double iTo);
  397.     /// set y-axis - ranges
  398.     Gnuplot& set_yrange(const double iFrom,
  399.                         const double iTo);
  400.     /// set z-axis - ranges
  401.     Gnuplot& set_zrange(const double iFrom,
  402.                         const double iTo);
  403.     /// autoscale axis (set by default) of xaxis
  404.     ///
  405.     /// \param ---
  406.     ///
  407.     /// \return <-- reference to the gnuplot object
  408.     // -----------------------------------------------
  409.     inline Gnuplot& set_xautoscale(){cmd("set xrange restore");cmd("set autoscale x");return *this;};
  410.  
  411.     // -----------------------------------------------
  412.     /// autoscale axis (set by default) of yaxis
  413.     ///
  414.     /// \param ---
  415.     ///
  416.     /// \return <-- reference to the gnuplot object
  417.     // -----------------------------------------------
  418.     inline Gnuplot& set_yautoscale(){cmd("set yrange restore");cmd("set autoscale y");return *this;};
  419.  
  420.     // -----------------------------------------------
  421.     /// autoscale axis (set by default) of zaxis
  422.     ///
  423.     /// \param ---
  424.     ///
  425.     /// \return <-- reference to the gnuplot object
  426.     // -----------------------------------------------
  427.     inline Gnuplot& set_zautoscale(){cmd("set zrange restore");cmd("set autoscale z");return *this;};
  428.  
  429.  
  430.     /// turns on/off log scaling for the specified xaxis (logscale is not set by default)
  431.     Gnuplot& set_xlogscale(const double base = 10);
  432.     /// turns on/off log scaling for the specified yaxis (logscale is not set by default)
  433.     Gnuplot& set_ylogscale(const double base = 10);
  434.     /// turns on/off log scaling for the specified zaxis (logscale is not set by default)
  435.     Gnuplot& set_zlogscale(const double base = 10);
  436.  
  437.     // -----------------------------------------------
  438.     /// turns off log scaling for the x axis
  439.     ///
  440.     /// \param ---
  441.     ///
  442.     /// \return <-- reference to the gnuplot object
  443.     // ----------------------------------------------- 
  444.     inline Gnuplot& unset_xlogscale(){cmd("unset logscale x"); return *this;};
  445.  
  446.     // -----------------------------------------------
  447.     /// turns off log scaling for the y axis
  448.     ///
  449.     /// \param ---
  450.     ///
  451.     /// \return <-- reference to the gnuplot object
  452.     // ----------------------------------------------- 
  453.     inline Gnuplot& unset_ylogscale(){cmd("unset logscale y"); return *this;};
  454.  
  455.     // -----------------------------------------------
  456.     /// turns off log scaling for the z axis
  457.     ///
  458.     /// \param ---
  459.     ///
  460.     /// \return <-- reference to the gnuplot object
  461.     // -----------------------------------------------     
  462.     inline Gnuplot& unset_zlogscale(){cmd("unset logscale z"); return *this;};
  463.  
  464.  
  465.     /// set palette range (autoscale by default)
  466.     Gnuplot& set_cbrange(const double iFrom, const double iTo);
  467.  
  468.  
  469.     //----------------------------------------------------------------------------------
  470.     // plot
  471.  
  472.     /// plot a single std::vector: x
  473.     ///   from file
  474.     Gnuplot& plotfile_x(const std::string &filename,
  475.                         const unsigned int column = 1,
  476.                         const std::string &title = "");
  477.     ///   from std::vector
  478.     template<typename X>
  479.     Gnuplot& plot_x(const X& x, const std::string &title = "");
  480.  
  481.  
  482.     /// plot x,y pairs: x y
  483.     ///   from file
  484.     Gnuplot& plotfile_xy(const std::string &filename,
  485.                          const unsigned int column_x = 1,
  486.                          const unsigned int column_y = 2,
  487.                          const std::string &title = "");
  488.     ///   from data
  489.     template<typename X, typename Y>
  490.     Gnuplot& plot_xy(const X& x, const Y& y, const std::string &title = "");
  491.  
  492.  
  493.     /// plot x,y pairs with dy errorbars: x y dy
  494.     ///   from file
  495.     Gnuplot& plotfile_xy_err(const std::string &filename,
  496.                              const unsigned int column_x  = 1,
  497.                              const unsigned int column_y  = 2,
  498.                              const unsigned int column_dy = 3,
  499.                              const std::string &title = "");
  500.     ///   from data
  501.     template<typename X, typename Y, typename E>
  502.     Gnuplot& plot_xy_err(const X &x, const Y &y, const E &dy,
  503.                          const std::string &title = "");
  504.  
  505.  
  506.     /// plot x,y,z triples: x y z
  507.     ///   from file
  508.     Gnuplot& plotfile_xyz(const std::string &filename,
  509.                           const unsigned int column_x = 1,
  510.                           const unsigned int column_y = 2,
  511.                           const unsigned int column_z = 3,
  512.                           const std::string &title = "");
  513.     ///   from std::vector
  514.     template<typename X, typename Y, typename Z>
  515.     Gnuplot& plot_xyz(const X &x,
  516.                       const Y &y,
  517.                       const Z &z,
  518.                       const std::string &title = "");
  519.  
  520.  
  521.  
  522.     /// plot an equation of the form: y = ax + b, you supply a and b
  523.     Gnuplot& plot_slope(const double a,
  524.                         const double b,
  525.                         const std::string &title = "");
  526.  
  527.  
  528.     /// plot an equation supplied as a std::string y=f(x), write only the function f(x) not y=
  529.     /// the independent variable has to be x
  530.     /// binary operators: ** exponentiation, * multiply, / divide, + add, - substract, % modulo
  531.     /// unary operators: - minus, ! factorial
  532.     /// elementary functions: rand(x), abs(x), sgn(x), ceil(x), floor(x), int(x), imag(x), real(x), arg(x),
  533.     ///   sqrt(x), exp(x), log(x), log10(x), sin(x), cos(x), tan(x), asin(x), acos(x), atan(x), atan2(y,x),
  534.     ///   sinh(x), cosh(x), tanh(x), asinh(x), acosh(x), atanh(x)
  535.     /// special functions: erf(x), erfc(x), inverf(x), gamma(x), igamma(a,x), lgamma(x), ibeta(p,q,x),
  536.     ///   besj0(x), besj1(x), besy0(x), besy1(x), lambertw(x)
  537.     /// statistical fuctions: norm(x), invnorm(x)
  538.     Gnuplot& plot_equation(const std::string &equation,
  539.                            const std::string &title = "");
  540.  
  541.     /// plot an equation supplied as a std::string z=f(x,y), write only the function f(x,y) not z=
  542.     /// the independent variables have to be x and y
  543.     Gnuplot& plot_equation3d(const std::string &equation,
  544.                              const std::string &title = "");
  545.  
  546.  
  547.     /// plot image
  548.     Gnuplot& plot_image(const unsigned char *ucPicBuf,
  549.                         const unsigned int iWidth,
  550.                         const unsigned int iHeight,
  551.                         const std::string &title = "");
  552.  
  553.  
  554.     //----------------------------------------------------------------------------------
  555.     ///\brief replot repeats the last plot or splot command.
  556.     ///  this can be useful for viewing a plot with different set options,
  557.     ///  or when generating the same plot for several devices (showonscreen, savetops)
  558.     ///
  559.     /// \param ---
  560.     ///
  561.     /// \return ---
  562.     //----------------------------------------------------------------------------------
  563.     inline Gnuplot& replot(void){if (nplots > 0) cmd("replot");return *this;};
  564.  
  565.     /// resets a gnuplot session (next plot will erase previous ones)
  566.     Gnuplot& reset_plot();
  567.  
  568.     /// resets a gnuplot session and sets all variables to default
  569.     Gnuplot& reset_all();
  570.  
  571.     /// deletes temporary files
  572.     void remove_tmpfiles();
  573.  
  574.     // -------------------------------------------------------------------
  575.     /// \brief Is the gnuplot session valid ??
  576.     ///
  577.     ///
  578.     /// \param ---
  579.     ///
  580.     /// \return true if valid, false if not
  581.     // -------------------------------------------------------------------
  582.     inline bool is_valid(){return(valid);};
  583.  
  584. };
  585.  
  586. //------------------------------------------------------------------------------
  587. //
  588. // initialize static data
  589. //
  590. int Gnuplot::tmpfile_num = 0;
  591.  
  592. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  593. std::string Gnuplot::m_sGNUPlotFileName = "pgnuplot.exe";
  594. std::string Gnuplot::m_sGNUPlotPath = "./";// "C:/Program\ Files (x86)/gnuplot/bin/";
  595. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  596. std::string Gnuplot::m_sGNUPlotFileName = "gnuplot";
  597. std::string Gnuplot::m_sGNUPlotPath = "/usr/local/bin/";
  598. #endif
  599.  
  600. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  601. std::string Gnuplot::terminal_std = "windows";
  602. #elif ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__)
  603. std::string Gnuplot::terminal_std = "x11";
  604. #elif defined(__APPLE__)
  605. std::string Gnuplot::terminal_std = "aqua";
  606. #endif
  607.  
  608. //------------------------------------------------------------------------------
  609. //
  610. // constructor: set a style during construction
  611. //
  612. inline Gnuplot::Gnuplot(const std::string &style)
  613.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  614.  
  615. {
  616.     init();
  617.     set_style(style);
  618. }
  619.  
  620. //------------------------------------------------------------------------------
  621. //
  622. // constructor: open a new session, plot a signal (x)
  623. //
  624. inline Gnuplot::Gnuplot(const std::vector<double> &x,
  625.                  const std::string &title,
  626.                  const std::string &style,
  627.                  const std::string &labelx,
  628.                  const std::string &labely)
  629.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  630. {
  631.     init();
  632.  
  633.     set_style(style);
  634.     set_xlabel(labelx);
  635.     set_ylabel(labely);
  636.  
  637.     plot_x(x,title);
  638. }
  639.  
  640.  
  641. //------------------------------------------------------------------------------
  642. //
  643. // constructor: open a new session, plot a signal (x,y)
  644. //
  645. inline Gnuplot::Gnuplot(const std::vector<double> &x,
  646.                  const std::vector<double> &y,
  647.                  const std::string &title,
  648.                  const std::string &style,
  649.                  const std::string &labelx,
  650.                  const std::string &labely)
  651.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  652. {
  653.     init();
  654.  
  655.     set_style(style);
  656.     set_xlabel(labelx);
  657.     set_ylabel(labely);
  658.  
  659.     plot_xy(x,y,title);
  660. }
  661.  
  662.  
  663. //------------------------------------------------------------------------------
  664. //
  665. // constructor: open a new session, plot a signal (x,y,z)
  666. //
  667. inline Gnuplot::Gnuplot(const std::vector<double> &x,
  668.                  const std::vector<double> &y,
  669.                  const std::vector<double> &z,
  670.                  const std::string &title,
  671.                  const std::string &style,
  672.                  const std::string &labelx,
  673.                  const std::string &labely,
  674.                  const std::string &labelz)
  675.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  676. {
  677.     init();
  678.  
  679.     set_style(style);
  680.     set_xlabel(labelx);
  681.     set_ylabel(labely);
  682.     set_zlabel(labelz);
  683.  
  684.     plot_xyz(x,y,z,title);
  685. }
  686.  
  687.  
  688. //------------------------------------------------------------------------------
  689. //
  690. /// Plots a 2d graph from a list of doubles: x
  691. //
  692. template<typename X>
  693. Gnuplot& Gnuplot::plot_x(const X& x, const std::string &title)
  694. {
  695.     if (x.size() == 0)
  696.     {
  697.         throw GnuplotException("std::vector too small");
  698.         return *this;
  699.     }
  700.  
  701.     std::ofstream tmp;
  702.     std::string name = create_tmpfile(tmp);
  703.     if (name == "")
  704.         return *this;
  705.  
  706.     //
  707.     // write the data to file
  708.     //
  709.     for (unsigned int i = 0; i < x.size(); i++)
  710.         tmp << x[i] << std::endl;
  711.  
  712.     tmp.flush();
  713.     tmp.close();
  714.  
  715.  
  716.     plotfile_x(name, 1, title);
  717.  
  718.     return *this;
  719. }
  720.  
  721.  
  722. //------------------------------------------------------------------------------
  723. //
  724. /// Plots a 2d graph from a list of doubles: x y
  725. //
  726. template<typename X, typename Y>
  727. Gnuplot& Gnuplot::plot_xy(const X& x, const Y& y, const std::string &title)
  728. {
  729.     if (x.size() == 0 || y.size() == 0)
  730.     {
  731.         throw GnuplotException("std::vectors too small");
  732.         return *this;
  733.     }
  734.  
  735.     if (x.size() != y.size())
  736.     {
  737.         throw GnuplotException("Length of the std::vectors differs");
  738.         return *this;
  739.     }
  740.  
  741.  
  742.     std::ofstream tmp;
  743.     std::string name = create_tmpfile(tmp);
  744.     if (name == "")
  745.         return *this;
  746.  
  747.     //
  748.     // write the data to file
  749.     //
  750.     for (unsigned int i = 0; i < x.size(); i++)
  751.         tmp << x[i] << " " << y[i] << std::endl;
  752.  
  753.     tmp.flush();
  754.     tmp.close();
  755.  
  756.  
  757.     plotfile_xy(name, 1, 2, title);
  758.  
  759.     return *this;
  760. }
  761.  
  762. ///-----------------------------------------------------------------------------
  763. ///
  764. /// plot x,y pairs with dy errorbars
  765. ///
  766. template<typename X, typename Y, typename E>
  767. Gnuplot& Gnuplot::plot_xy_err(const X &x,
  768.                               const Y &y,
  769.                               const E &dy,
  770.                               const std::string &title)
  771. {
  772.     if (x.size() == 0 || y.size() == 0 || dy.size() == 0)
  773.     {
  774.         throw GnuplotException("std::vectors too small");
  775.         return *this;
  776.     }
  777.  
  778.     if (x.size() != y.size() || y.size() != dy.size())
  779.     {
  780.         throw GnuplotException("Length of the std::vectors differs");
  781.         return *this;
  782.     }
  783.  
  784.  
  785.     std::ofstream tmp;
  786.     std::string name = create_tmpfile(tmp);
  787.     if (name == "")
  788.         return *this;
  789.  
  790.     //
  791.     // write the data to file
  792.     //
  793.     for (unsigned int i = 0; i < x.size(); i++)
  794.         tmp << x[i] << " " << y[i] << " " << dy[i] << std::endl;
  795.  
  796.     tmp.flush();
  797.     tmp.close();
  798.  
  799.  
  800.     // Do the actual plot
  801.     plotfile_xy_err(name, 1, 2, 3, title);
  802.  
  803.     return *this;
  804. }
  805.  
  806.  
  807. //------------------------------------------------------------------------------
  808. //
  809. // Plots a 3d graph from a list of doubles: x y z
  810. //
  811. template<typename X, typename Y, typename Z>
  812. Gnuplot& Gnuplot::plot_xyz(const X &x,
  813.                            const Y &y,
  814.                            const Z &z,
  815.                            const std::string &title)
  816. {
  817.     if (x.size() == 0 || y.size() == 0 || z.size() == 0)
  818.     {
  819.         throw GnuplotException("std::vectors too small");
  820.         return *this;
  821.     }
  822.  
  823.     if (x.size() != y.size() || x.size() != z.size())
  824.     {
  825.         throw GnuplotException("Length of the std::vectors differs");
  826.         return *this;
  827.     }
  828.  
  829.  
  830.     std::ofstream tmp;
  831.     std::string name = create_tmpfile(tmp);
  832.     if (name == "")
  833.         return *this;
  834.  
  835.     //
  836.     // write the data to file
  837.     //
  838.     for (unsigned int i = 0; i < x.size(); i++)
  839.         tmp << x[i] << " " << y[i] << " " << z[i] <<std::endl;
  840.  
  841.     tmp.flush();
  842.     tmp.close();
  843.  
  844.  
  845.     plotfile_xyz(name, 1, 2, 3, title);
  846.  
  847.     return *this;
  848. }
  849.  
  850.  
  851. //------------------------------------------------------------------------------
  852. //
  853. // define static member function: set Gnuplot path manual
  854. //   for windows: path with slash '/' not backslash '\'
  855. //
  856. bool Gnuplot::set_GNUPlotPath(const std::string &path)
  857. {
  858.  
  859.     std::string tmp = path + "/" + Gnuplot::m_sGNUPlotFileName;
  860.  
  861.  
  862. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  863.     if ( Gnuplot::file_exists(tmp,0) ) // check existence
  864. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  865.     if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission
  866. #endif
  867.     {
  868.         Gnuplot::m_sGNUPlotPath = path;
  869.         return true;
  870.     }
  871.     else
  872.     {
  873.         Gnuplot::m_sGNUPlotPath.clear();
  874.         return false;
  875.     }
  876. }
  877.  
  878.  
  879. //------------------------------------------------------------------------------
  880. //
  881. // define static member function: set standart terminal, used by showonscreen
  882. //  defaults: Windows - win, Linux - x11, Mac - aqua
  883. //
  884. void Gnuplot::set_terminal_std(const std::string &type)
  885. {
  886. #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  887.     if (type.find("x11") != std::string::npos && getenv("DISPLAY") == NULL)
  888.     {
  889.         throw GnuplotException("Can't find DISPLAY variable");
  890.     }
  891. #endif
  892.  
  893.  
  894.     Gnuplot::terminal_std = type;
  895.     return;
  896. }
  897.  
  898.  
  899. //------------------------------------------------------------------------------
  900. //
  901. // A string tokenizer taken from http://www.sunsite.ualberta.ca/Documentation/
  902. // /Gnu/libstdc++-2.90.8/html/21_strings/stringtok_std_h.txt
  903. //
  904. template <typename Container>
  905. void stringtok (Container &container,
  906.                 std::string const &in,
  907.                 const char * const delimiters = " \t\n")
  908. {
  909.     const std::string::size_type len = in.length();
  910.           std::string::size_type i = 0;
  911.  
  912.     while ( i < len )
  913.     {
  914.         // eat leading whitespace
  915.         i = in.find_first_not_of (delimiters, i);
  916.  
  917.         if (i == std::string::npos)
  918.             return;   // nothing left but white space
  919.  
  920.         // find the end of the token
  921.         std::string::size_type j = in.find_first_of (delimiters, i);
  922.  
  923.         // push token
  924.         if (j == std::string::npos)
  925.         {
  926.             container.push_back (in.substr(i));
  927.             return;
  928.         }
  929.         else
  930.             container.push_back (in.substr(i, j-i));
  931.  
  932.         // set up for next loop
  933.         i = j + 1;
  934.     }
  935.  
  936.     return;
  937. }
  938.  
  939.  
  940. //------------------------------------------------------------------------------
  941. //
  942. // Destructor: needed to delete temporary files
  943. //
  944. Gnuplot::~Gnuplot()
  945. {
  946. //  remove_tmpfiles();
  947.  
  948.     // A stream opened by popen() should be closed by pclose()
  949. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  950.     if (_pclose(gnucmd) == -1)
  951. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  952.     if (pclose(gnucmd) == -1)
  953. #endif
  954.         throw GnuplotException("Problem closing communication to gnuplot");
  955. }
  956.  
  957.  
  958. //------------------------------------------------------------------------------
  959. //
  960. // Resets a gnuplot session (next plot will erase previous ones)
  961. //
  962. Gnuplot& Gnuplot::reset_plot()
  963. {
  964. //  remove_tmpfiles();
  965.  
  966.     nplots = 0;
  967.  
  968.     return *this;
  969. }
  970.  
  971.  
  972. //------------------------------------------------------------------------------
  973. //
  974. // resets a gnuplot session and sets all varibles to default
  975. //
  976. Gnuplot& Gnuplot::reset_all()
  977. {
  978. //  remove_tmpfiles();
  979.  
  980.     nplots = 0;
  981.     cmd("reset");
  982.     cmd("clear");
  983.     pstyle = "points";
  984.     smooth = "";
  985.     showonscreen();
  986.  
  987.     return *this;
  988. }
  989.  
  990.  
  991. //------------------------------------------------------------------------------
  992. //
  993. // Change the plotting style of a gnuplot session
  994. //
  995. Gnuplot& Gnuplot::set_style(const std::string &stylestr)
  996. {
  997.     if (stylestr.find("lines")          == std::string::npos  &&
  998.         stylestr.find("points")         == std::string::npos  &&
  999.         stylestr.find("linespoints")    == std::string::npos  &&
  1000.         stylestr.find("impulses")       == std::string::npos  &&
  1001.         stylestr.find("dots")           == std::string::npos  &&
  1002.         stylestr.find("steps")          == std::string::npos  &&
  1003.         stylestr.find("fsteps")         == std::string::npos  &&
  1004.         stylestr.find("histeps")        == std::string::npos  &&
  1005.         stylestr.find("boxes")          == std::string::npos  &&  // 1-4 columns of data are required
  1006.         stylestr.find("filledcurves")   == std::string::npos  &&
  1007.         stylestr.find("histograms")     == std::string::npos  )   //only for one data column
  1008. //        stylestr.find("labels")         == std::string::npos  &&  // 3 columns of data are required
  1009. //        stylestr.find("xerrorbars")     == std::string::npos  &&  // 3-4 columns of data are required
  1010. //        stylestr.find("xerrorlines")    == std::string::npos  &&  // 3-4 columns of data are required
  1011. //        stylestr.find("errorbars")      == std::string::npos  &&  // 3-4 columns of data are required
  1012. //        stylestr.find("errorlines")     == std::string::npos  &&  // 3-4 columns of data are required
  1013. //        stylestr.find("yerrorbars")     == std::string::npos  &&  // 3-4 columns of data are required
  1014. //        stylestr.find("yerrorlines")    == std::string::npos  &&  // 3-4 columns of data are required
  1015. //        stylestr.find("boxerrorbars")   == std::string::npos  &&  // 3-5 columns of data are required
  1016. //        stylestr.find("xyerrorbars")    == std::string::npos  &&  // 4,6,7 columns of data are required
  1017. //        stylestr.find("xyerrorlines")   == std::string::npos  &&  // 4,6,7 columns of data are required
  1018. //        stylestr.find("boxxyerrorbars") == std::string::npos  &&  // 4,6,7 columns of data are required
  1019. //        stylestr.find("financebars")    == std::string::npos  &&  // 5 columns of data are required
  1020. //        stylestr.find("candlesticks")   == std::string::npos  &&  // 5 columns of data are required
  1021. //        stylestr.find("vectors")        == std::string::npos  &&
  1022. //        stylestr.find("image")          == std::string::npos  &&
  1023. //        stylestr.find("rgbimage")       == std::string::npos  &&
  1024. //        stylestr.find("pm3d")           == std::string::npos  )
  1025.     {
  1026.         pstyle = std::string("points");
  1027.     }
  1028.     else
  1029.     {
  1030.         pstyle = stylestr;
  1031.     }
  1032.  
  1033.     return *this;
  1034. }
  1035.  
  1036.  
  1037. //------------------------------------------------------------------------------
  1038. //
  1039. // smooth: interpolation and approximation of data
  1040. //
  1041. Gnuplot& Gnuplot::set_smooth(const std::string &stylestr)
  1042. {
  1043.     if (stylestr.find("unique")    == std::string::npos  &&
  1044.         stylestr.find("frequency") == std::string::npos  &&
  1045.         stylestr.find("csplines")  == std::string::npos  &&
  1046.         stylestr.find("acsplines") == std::string::npos  &&
  1047.         stylestr.find("bezier")    == std::string::npos  &&
  1048.         stylestr.find("sbezier")   == std::string::npos  )
  1049.     {
  1050.         smooth = "";
  1051.     }
  1052.     else
  1053.     {
  1054.         smooth = stylestr;
  1055.     }
  1056.  
  1057.     return *this;
  1058. }
  1059.  
  1060.  
  1061. //------------------------------------------------------------------------------
  1062. //
  1063. // sets terminal type to windows / x11
  1064. //
  1065. Gnuplot& Gnuplot::showonscreen()
  1066. {
  1067.     cmd("set output");
  1068.     cmd("set terminal " + Gnuplot::terminal_std);
  1069.  
  1070.     return *this;
  1071. }
  1072.  
  1073. //------------------------------------------------------------------------------
  1074. //
  1075. // saves a gnuplot session to a postscript file
  1076. //
  1077. Gnuplot& Gnuplot::savetops(const std::string &filename)
  1078. {
  1079.     cmd("set terminal postscript color");
  1080.  
  1081.     std::ostringstream cmdstr;
  1082.     cmdstr << "set output \"" << filename << ".ps\"";
  1083.     cmd(cmdstr.str());
  1084.  
  1085.     return *this;
  1086. }
  1087.  
  1088. //------------------------------------------------------------------------------
  1089. //
  1090. // Switches legend on
  1091. //
  1092. Gnuplot& Gnuplot::set_legend(const std::string &position)
  1093. {
  1094.     std::ostringstream cmdstr;
  1095.     cmdstr << "set key " << position;
  1096.  
  1097.     cmd(cmdstr.str());
  1098.  
  1099.     return *this;
  1100. }
  1101.  
  1102. //------------------------------------------------------------------------------
  1103. //
  1104. // turns on log scaling for the x axis
  1105. //
  1106. Gnuplot& Gnuplot::set_xlogscale(const double base)
  1107. {
  1108.     std::ostringstream cmdstr;
  1109.  
  1110.     cmdstr << "set logscale x " << base;
  1111.     cmd(cmdstr.str());
  1112.  
  1113.     return *this;
  1114. }
  1115.  
  1116. //------------------------------------------------------------------------------
  1117. //
  1118. // turns on log scaling for the y axis
  1119. //
  1120. Gnuplot& Gnuplot::set_ylogscale(const double base)
  1121. {
  1122.     std::ostringstream cmdstr;
  1123.  
  1124.     cmdstr << "set logscale y " << base;
  1125.     cmd(cmdstr.str());
  1126.  
  1127.     return *this;
  1128. }
  1129.  
  1130. //------------------------------------------------------------------------------
  1131. //
  1132. // turns on log scaling for the z axis
  1133. //
  1134. Gnuplot& Gnuplot::set_zlogscale(const double base)
  1135. {
  1136.     std::ostringstream cmdstr;
  1137.  
  1138.     cmdstr << "set logscale z " << base;
  1139.     cmd(cmdstr.str());
  1140.  
  1141.     return *this;
  1142. }
  1143.  
  1144. //------------------------------------------------------------------------------
  1145. //
  1146. // scales the size of the points used in plots
  1147. //
  1148. Gnuplot& Gnuplot::set_pointsize(const double pointsize)
  1149. {
  1150.     std::ostringstream cmdstr;
  1151.     cmdstr << "set pointsize " << pointsize;
  1152.     cmd(cmdstr.str());
  1153.  
  1154.     return *this;
  1155. }
  1156.  
  1157. //------------------------------------------------------------------------------
  1158. //
  1159. // set isoline density (grid) for plotting functions as surfaces
  1160. //
  1161. Gnuplot& Gnuplot::set_samples(const int samples)
  1162. {
  1163.     std::ostringstream cmdstr;
  1164.     cmdstr << "set samples " << samples;
  1165.     cmd(cmdstr.str());
  1166.  
  1167.     return *this;
  1168. }
  1169.  
  1170.  
  1171. //------------------------------------------------------------------------------
  1172. //
  1173. // set isoline density (grid) for plotting functions as surfaces
  1174. //
  1175. Gnuplot& Gnuplot::set_isosamples(const int isolines)
  1176. {
  1177.     std::ostringstream cmdstr;
  1178.     cmdstr << "set isosamples " << isolines;
  1179.     cmd(cmdstr.str());
  1180.  
  1181.     return *this;
  1182. }
  1183.  
  1184.  
  1185. //------------------------------------------------------------------------------
  1186. //
  1187. // enables contour drawing for surfaces set contour {base | surface | both}
  1188. //
  1189.  
  1190. Gnuplot& Gnuplot::set_contour(const std::string &position)
  1191. {
  1192.     if (position.find("base")    == std::string::npos  &&
  1193.         position.find("surface") == std::string::npos  &&
  1194.         position.find("both")    == std::string::npos  )
  1195.     {
  1196.         cmd("set contour base");
  1197.     }
  1198.     else
  1199.     {
  1200.         cmd("set contour " + position);
  1201.     }
  1202.  
  1203.     return *this;
  1204. }
  1205.  
  1206. //------------------------------------------------------------------------------
  1207. //
  1208. // set labels
  1209. //
  1210. // set the xlabel
  1211. Gnuplot& Gnuplot::set_xlabel(const std::string &label)
  1212. {
  1213.     std::ostringstream cmdstr;
  1214.  
  1215.     cmdstr << "set xlabel \"" << label << "\"";
  1216.     cmd(cmdstr.str());
  1217.  
  1218.     return *this;
  1219. }
  1220.  
  1221. //------------------------------------------------------------------------------
  1222. // set the ylabel
  1223. //
  1224. Gnuplot& Gnuplot::set_ylabel(const std::string &label)
  1225. {
  1226.     std::ostringstream cmdstr;
  1227.  
  1228.     cmdstr << "set ylabel \"" << label << "\"";
  1229.     cmd(cmdstr.str());
  1230.  
  1231.     return *this;
  1232. }
  1233.  
  1234. //------------------------------------------------------------------------------
  1235. // set the zlabel
  1236. //
  1237. Gnuplot& Gnuplot::set_zlabel(const std::string &label)
  1238. {
  1239.     std::ostringstream cmdstr;
  1240.  
  1241.     cmdstr << "set zlabel \"" << label << "\"";
  1242.     cmd(cmdstr.str());
  1243.  
  1244.     return *this;
  1245. }
  1246.  
  1247. //------------------------------------------------------------------------------
  1248. //
  1249. // set range
  1250. //
  1251. // set the xrange
  1252. Gnuplot& Gnuplot::set_xrange(const double iFrom,
  1253.                              const double iTo)
  1254. {
  1255.     std::ostringstream cmdstr;
  1256.  
  1257.     cmdstr << "set xrange[" << iFrom << ":" << iTo << "]";
  1258.     cmd(cmdstr.str());
  1259.  
  1260.     return *this;
  1261. }
  1262.  
  1263. //------------------------------------------------------------------------------
  1264. // set the yrange
  1265. //
  1266. Gnuplot& Gnuplot::set_yrange(const double iFrom,
  1267.                              const double iTo)
  1268. {
  1269.     std::ostringstream cmdstr;
  1270.  
  1271.     cmdstr << "set yrange[" << iFrom << ":" << iTo << "]";
  1272.     cmd(cmdstr.str());
  1273.  
  1274.     return *this;
  1275. }
  1276.  
  1277. //------------------------------------------------------------------------------
  1278. // set the zrange
  1279. //
  1280. Gnuplot& Gnuplot::set_zrange(const double iFrom,
  1281.                              const double iTo)
  1282. {
  1283.     std::ostringstream cmdstr;
  1284.  
  1285.     cmdstr << "set zrange[" << iFrom << ":" << iTo << "]";
  1286.     cmd(cmdstr.str());
  1287.  
  1288.     return *this;
  1289. }
  1290.  
  1291. //------------------------------------------------------------------------------
  1292. //
  1293. // set the palette range
  1294. //
  1295. Gnuplot& Gnuplot::set_cbrange(const double iFrom,
  1296.                               const double iTo)
  1297. {
  1298.     std::ostringstream cmdstr;
  1299.  
  1300.     cmdstr << "set cbrange[" << iFrom << ":" << iTo << "]";
  1301.     cmd(cmdstr.str());
  1302.  
  1303.     return *this;
  1304. }
  1305.  
  1306. //------------------------------------------------------------------------------
  1307. //
  1308. // Plots a linear equation y=ax+b (where you supply the
  1309. // slope a and intercept b)
  1310. //
  1311. Gnuplot& Gnuplot::plot_slope(const double a,
  1312.                              const double b,
  1313.                              const std::string &title)
  1314. {
  1315.     std::ostringstream cmdstr;
  1316.     //
  1317.     // command to be sent to gnuplot
  1318.     //
  1319.     if (nplots > 0  &&  two_dim == true)
  1320.         cmdstr << "replot ";
  1321.     else
  1322.         cmdstr << "plot ";
  1323.  
  1324.     cmdstr << a << " * x + " << b << " title \"";
  1325.  
  1326.     if (title == "")
  1327.         cmdstr << "f(x) = " << a << " * x + " << b;
  1328.     else
  1329.         cmdstr << title;
  1330.  
  1331.     cmdstr << "\" with " << pstyle;
  1332.  
  1333.     //
  1334.     // Do the actual plot
  1335.     //
  1336.     cmd(cmdstr.str());
  1337.  
  1338.     return *this;
  1339. }
  1340.  
  1341. //------------------------------------------------------------------------------
  1342. //
  1343. // Plot an equation supplied as a std::string y=f(x) (only f(x) expected)
  1344. //
  1345. Gnuplot& Gnuplot::plot_equation(const std::string &equation,
  1346.                                 const std::string &title)
  1347. {
  1348.     std::ostringstream cmdstr;
  1349.     //
  1350.     // command to be sent to gnuplot
  1351.     //
  1352.     if (nplots > 0  &&  two_dim == true)
  1353.         cmdstr << "replot ";
  1354.     else
  1355.         cmdstr << "plot ";
  1356.  
  1357.     cmdstr << equation << " title \"";
  1358.  
  1359.     if (title == "")
  1360.         cmdstr << "f(x) = " << equation;
  1361.     else
  1362.         cmdstr << title;
  1363.  
  1364.     cmdstr << "\" with " << pstyle;
  1365.  
  1366.     //
  1367.     // Do the actual plot
  1368.     //
  1369.     cmd(cmdstr.str());
  1370.  
  1371.     return *this;
  1372. }
  1373.  
  1374. //------------------------------------------------------------------------------
  1375. //
  1376. // plot an equation supplied as a std::string y=(x)
  1377. //
  1378. Gnuplot& Gnuplot::plot_equation3d(const std::string &equation,
  1379.                                   const std::string &title)
  1380. {
  1381.     std::ostringstream cmdstr;
  1382.     //
  1383.     // command to be sent to gnuplot
  1384.     //
  1385.     if (nplots > 0  &&  two_dim == false)
  1386.         cmdstr << "replot ";
  1387.     else
  1388.         cmdstr << "splot ";
  1389.  
  1390.     cmdstr << equation << " title \"";
  1391.  
  1392.     if (title == "")
  1393.         cmdstr << "f(x,y) = " << equation;
  1394.     else
  1395.         cmdstr << title;
  1396.  
  1397.     cmdstr << "\" with " << pstyle;
  1398.  
  1399.     //
  1400.     // Do the actual plot
  1401.     //
  1402.     cmd(cmdstr.str());
  1403.  
  1404.     return *this;
  1405. }
  1406.  
  1407.  
  1408. //------------------------------------------------------------------------------
  1409. //
  1410. // Plots a 2d graph from a list of doubles (x) saved in a file
  1411. //
  1412. Gnuplot& Gnuplot::plotfile_x(const std::string &filename,
  1413.                              const unsigned int column,
  1414.                              const std::string &title)
  1415. {
  1416.     //
  1417.     // check if file exists
  1418.     //
  1419.     file_available(filename);
  1420.  
  1421.  
  1422.     std::ostringstream cmdstr;
  1423.     //
  1424.     // command to be sent to gnuplot
  1425.     //
  1426.     if (nplots > 0  &&  two_dim == true)
  1427.         cmdstr << "replot ";
  1428.     else
  1429.         cmdstr << "plot ";
  1430.  
  1431.     cmdstr << "\"" << filename << "\" using " << column;
  1432.  
  1433.     if (title == "")
  1434.         cmdstr << " notitle ";
  1435.     else
  1436.         cmdstr << " title \"" << title << "\" ";
  1437.  
  1438.     if(smooth == "")
  1439.         cmdstr << "with " << pstyle;
  1440.     else
  1441.         cmdstr << "smooth " << smooth;
  1442.  
  1443.     //
  1444.     // Do the actual plot
  1445.     //
  1446.     cmd(cmdstr.str()); //nplots++; two_dim = true;  already in cmd();
  1447.  
  1448.     return *this;
  1449. }
  1450.  
  1451.  
  1452.  
  1453. //------------------------------------------------------------------------------
  1454. //
  1455. // Plots a 2d graph from a list of doubles (x y) saved in a file
  1456. //
  1457. Gnuplot& Gnuplot::plotfile_xy(const std::string &filename,
  1458.                               const unsigned int column_x,
  1459.                               const unsigned int column_y,
  1460.                               const std::string &title)
  1461. {
  1462.     //
  1463.     // check if file exists
  1464.     //
  1465.     file_available(filename);
  1466.  
  1467.  
  1468.     std::ostringstream cmdstr;
  1469.     //
  1470.     // command to be sent to gnuplot
  1471.     //
  1472.     if (nplots > 0  &&  two_dim == true)
  1473.         cmdstr << "replot ";
  1474.     else
  1475.         cmdstr << "plot ";
  1476.  
  1477.     cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y;
  1478.  
  1479.     if (title == "")
  1480.         cmdstr << " notitle ";
  1481.     else
  1482.         cmdstr << " title \"" << title << "\" ";
  1483.  
  1484.     if(smooth == "")
  1485.         cmdstr << "with " << pstyle;
  1486.     else
  1487.         cmdstr << "smooth " << smooth;
  1488.  
  1489.     //
  1490.     // Do the actual plot
  1491.     //
  1492.     cmd(cmdstr.str());
  1493.  
  1494.     return *this;
  1495. }
  1496.  
  1497.  
  1498. //------------------------------------------------------------------------------
  1499. //
  1500. // Plots a 2d graph with errorbars from a list of doubles (x y dy) in a file
  1501. //
  1502. Gnuplot& Gnuplot::plotfile_xy_err(const std::string &filename,
  1503.                                   const unsigned int column_x,
  1504.                                   const unsigned int column_y,
  1505.                                   const unsigned int column_dy,
  1506.                                   const std::string &title)
  1507. {
  1508.     //
  1509.     // check if file exists
  1510.     //
  1511.     file_available(filename);
  1512.  
  1513.     std::ostringstream cmdstr;
  1514.     //
  1515.     // command to be sent to gnuplot
  1516.     //
  1517.     if (nplots > 0  &&  two_dim == true)
  1518.         cmdstr << "replot ";
  1519.     else
  1520.         cmdstr << "plot ";
  1521.  
  1522.     cmdstr << "\"" << filename << "\" using "
  1523.            << column_x << ":" << column_y << ":" << column_dy
  1524.            << " with errorbars ";
  1525.  
  1526.     if (title == "")
  1527.         cmdstr << " notitle ";
  1528.     else
  1529.         cmdstr << " title \"" << title << "\" ";
  1530.  
  1531.     //
  1532.     // Do the actual plot
  1533.     //
  1534.     cmd(cmdstr.str());
  1535.  
  1536.     return *this;
  1537. }
  1538.  
  1539.  
  1540. //------------------------------------------------------------------------------
  1541. //
  1542. // Plots a 3d graph from a list of doubles (x y z) saved in a file
  1543. //
  1544. Gnuplot& Gnuplot::plotfile_xyz(const std::string &filename,
  1545.                                const unsigned int column_x,
  1546.                                const unsigned int column_y,
  1547.                                const unsigned int column_z,
  1548.                                const std::string &title)
  1549. {
  1550.     //
  1551.     // check if file exists
  1552.     //
  1553.     file_available(filename);
  1554.  
  1555.     std::ostringstream cmdstr;
  1556.     //
  1557.     // command to be sent to gnuplot
  1558.     //
  1559.     if (nplots > 0  &&  two_dim == false)
  1560.         cmdstr << "replot ";
  1561.     else
  1562.         cmdstr << "splot ";
  1563.  
  1564.     cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y
  1565.            << ":" << column_z;
  1566.  
  1567.     if (title == "")
  1568.         cmdstr << " notitle with " << pstyle;
  1569.     else
  1570.         cmdstr << " title \"" << title << "\" with " << pstyle;
  1571.  
  1572.     //
  1573.     // Do the actual plot
  1574.     //
  1575.     cmd(cmdstr.str());
  1576.  
  1577.     return *this;
  1578. }
  1579.  
  1580.  
  1581.  
  1582. //------------------------------------------------------------------------------
  1583. //
  1584. /// *  note that this function is not valid for versions of GNUPlot below 4.2
  1585. //
  1586. Gnuplot& Gnuplot::plot_image(const unsigned char * ucPicBuf,
  1587.                              const unsigned int iWidth,
  1588.                              const unsigned int iHeight,
  1589.                              const std::string &title)
  1590. {
  1591.     std::ofstream tmp;
  1592.     std::string name = create_tmpfile(tmp);
  1593.     if (name == "")
  1594.         return *this;
  1595.  
  1596.     //
  1597.     // write the data to file
  1598.     //
  1599.     int iIndex = 0;
  1600.     for(int iRow = 0; iRow < iHeight; iRow++)
  1601.     {
  1602.         for(int iColumn = 0; iColumn < iWidth; iColumn++)
  1603.         {
  1604.             tmp << iColumn << " " << iRow  << " "
  1605.                 << static_cast<float>(ucPicBuf[iIndex++]) << std::endl;
  1606.         }
  1607.     }
  1608.  
  1609.     tmp.flush();
  1610.     tmp.close();
  1611.  
  1612.  
  1613.     std::ostringstream cmdstr;
  1614.     //
  1615.     // command to be sent to gnuplot
  1616.     //
  1617.     if (nplots > 0  &&  two_dim == true)
  1618.         cmdstr << "replot ";
  1619.     else
  1620.         cmdstr << "plot ";
  1621.  
  1622.     if (title == "")
  1623.         cmdstr << "\"" << name << "\" with image";
  1624.     else
  1625.         cmdstr << "\"" << name << "\" title \"" << title << "\" with image";
  1626.  
  1627.     //
  1628.     // Do the actual plot
  1629.     //
  1630.     cmd(cmdstr.str());
  1631.  
  1632.     return *this;
  1633. }
  1634.  
  1635.  
  1636.  
  1637. //------------------------------------------------------------------------------
  1638. //
  1639. // Sends a command to an active gnuplot session
  1640. //
  1641. Gnuplot& Gnuplot::cmd(const std::string &cmdstr)
  1642. {
  1643.     if( !(valid) )
  1644.     {
  1645.         return *this;
  1646.     }
  1647.  
  1648.  
  1649.     // int fputs ( const char * str, FILE * stream );
  1650.     // writes the string str to the stream.
  1651.     // The function begins copying from the address specified (str) until it
  1652.     // reaches the terminating null character ('\0'). This final
  1653.     // null-character is not copied to the stream.
  1654.     fputs( (cmdstr+"\n").c_str(), gnucmd );
  1655.  
  1656.     // int fflush ( FILE * stream );
  1657.     // If the given stream was open for writing and the last i/o operation was
  1658.     // an output operation, any unwritten data in the output buffer is written
  1659.     // to the file.  If the argument is a null pointer, all open files are
  1660.     // flushed.  The stream remains open after this call.
  1661.     fflush(gnucmd);
  1662.  
  1663.  
  1664.     if( cmdstr.find("replot") != std::string::npos )
  1665.     {
  1666.         return *this;
  1667.     }
  1668.     else if( cmdstr.find("splot") != std::string::npos )
  1669.     {
  1670.         two_dim = false;
  1671.         nplots++;
  1672.     }
  1673.     else if( cmdstr.find("plot") != std::string::npos )
  1674.     {
  1675.         two_dim = true;
  1676.         nplots++;
  1677.     }
  1678.  
  1679.     return *this;
  1680. }
  1681.  
  1682.  
  1683.  
  1684. //------------------------------------------------------------------------------
  1685. //
  1686. // Opens up a gnuplot session, ready to receive commands
  1687. //
  1688. void Gnuplot::init()
  1689. {
  1690.     // char * getenv ( const char * name );  get value of environment variable
  1691.     // Retrieves a C string containing the value of the environment variable
  1692.     // whose name is specified as argument.  If the requested variable is not
  1693.     // part of the environment list, the function returns a NULL pointer.
  1694. #if ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__)
  1695.     if (getenv("DISPLAY") == NULL)
  1696.     {
  1697.         valid = false;
  1698.         throw GnuplotException("Can't find DISPLAY variable");
  1699.     }
  1700. #endif
  1701.  
  1702.  
  1703.     // if gnuplot not available
  1704.     if (!Gnuplot::get_program_path())
  1705.     {
  1706.         valid = false;
  1707.         throw GnuplotException("Can't find gnuplot");
  1708.     }
  1709.  
  1710.  
  1711.     //
  1712.     // open pipe
  1713.     //
  1714.     std::string tmp = Gnuplot::m_sGNUPlotPath + "/" +
  1715.         Gnuplot::m_sGNUPlotFileName;
  1716.  
  1717.     // FILE *popen(const char *command, const char *mode);
  1718.     // The popen() function shall execute the command specified by the string
  1719.     // command, create a pipe between the calling program and the executed
  1720.     // command, and return a pointer to a stream that can be used to either read
  1721.     // from or write to the pipe.
  1722. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1723.     gnucmd = _popen(tmp.c_str(),"w");
  1724. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1725.     gnucmd = popen(tmp.c_str(),"w");
  1726. #endif
  1727.  
  1728.     // popen() shall return a pointer to an open stream that can be used to read
  1729.     // or write to the pipe.  Otherwise, it shall return a null pointer and may
  1730.     // set errno to indicate the error.
  1731.     if (!gnucmd)
  1732.     {
  1733.         valid = false;
  1734.         throw GnuplotException("Couldn't open connection to gnuplot");
  1735.     }
  1736.  
  1737.     nplots = 0;
  1738.     valid = true;
  1739.     smooth = "";
  1740.  
  1741.     //set terminal type
  1742.     showonscreen();
  1743.  
  1744.     return;
  1745. }
  1746.  
  1747.  
  1748. //------------------------------------------------------------------------------
  1749. //
  1750. // Find out if a command lives in m_sGNUPlotPath or in PATH
  1751. //
  1752. bool Gnuplot::get_program_path()
  1753. {
  1754.     //
  1755.     // first look in m_sGNUPlotPath for Gnuplot
  1756.     //
  1757.     std::string tmp = Gnuplot::m_sGNUPlotPath + "/" +
  1758.         Gnuplot::m_sGNUPlotFileName;
  1759.  
  1760. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1761.     if ( Gnuplot::file_exists(tmp,0) ) // check existence
  1762. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1763.     if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission
  1764. #endif
  1765.     {
  1766.         return true;
  1767.     }
  1768.  
  1769.  
  1770.     //
  1771.     // second look in PATH for Gnuplot
  1772.     //
  1773.     char *path;
  1774.     // Retrieves a C string containing the value of environment variable PATH
  1775.     path = getenv("PATH");
  1776.  
  1777.  
  1778.     if (path == NULL)
  1779.     {
  1780.         throw GnuplotException("Path is not set");
  1781.         return false;
  1782.     }
  1783.     else
  1784.     {
  1785.         std::list<std::string> ls;
  1786.  
  1787.         //split path (one long string) into list ls of strings
  1788. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1789.         stringtok(ls,path,";");
  1790. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1791.         stringtok(ls,path,":");
  1792. #endif
  1793.  
  1794.         // scan list for Gnuplot program files
  1795.         for (std::list<std::string>::const_iterator i = ls.begin();
  1796.                 i != ls.end(); ++i)
  1797.         {
  1798.             tmp = (*i) + "/" + Gnuplot::m_sGNUPlotFileName;
  1799. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1800.             if ( Gnuplot::file_exists(tmp,0) ) // check existence
  1801. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1802.             if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission
  1803. #endif
  1804.             {
  1805.                 Gnuplot::m_sGNUPlotPath = *i; // set m_sGNUPlotPath
  1806.                 return true;
  1807.             }
  1808.         }
  1809.  
  1810.         tmp = "Can't find gnuplot neither in PATH nor in \"" +
  1811.             Gnuplot::m_sGNUPlotPath + "\"";
  1812.         throw GnuplotException(tmp);
  1813.  
  1814.         Gnuplot::m_sGNUPlotPath = "";
  1815.         return false;
  1816.     }
  1817. }
  1818.  
  1819.  
  1820.  
  1821. //------------------------------------------------------------------------------
  1822. //
  1823. // check if file exists
  1824. //
  1825. bool Gnuplot::file_exists(const std::string &filename, int mode)
  1826. {
  1827.     if ( mode < 0 || mode > 7)
  1828.     {
  1829.         throw std::runtime_error("In function \"Gnuplot::file_exists\": mode\
  1830.                has to be an integer between 0 and 7");
  1831.         return false;
  1832.     }
  1833.  
  1834.     // int _access(const char *path, int mode);
  1835.     //  returns 0 if the file has the given mode,
  1836.     //  it returns -1 if the named file does not exist or is not accessible in
  1837.     //  the given mode
  1838.     // mode = 0 (F_OK) (default): checks file for existence only
  1839.     // mode = 1 (X_OK): execution permission
  1840.     // mode = 2 (W_OK): write permission
  1841.     // mode = 4 (R_OK): read permission
  1842.     // mode = 6       : read and write permission
  1843.     // mode = 7       : read, write and execution permission
  1844. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1845.     if (_access(filename.c_str(), mode) == 0)
  1846. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1847.     if (access(filename.c_str(), mode) == 0)
  1848. #endif
  1849.     {
  1850.         return true;
  1851.     }
  1852.     else
  1853.     {
  1854.         return false;
  1855.     }
  1856.  
  1857. }
  1858.  
  1859. bool Gnuplot::file_available(const std::string &filename){
  1860.     std::ostringstream except;
  1861.     if( Gnuplot::file_exists(filename,0) ) // check existence
  1862.     {
  1863.         if( !(Gnuplot::file_exists(filename,4)) ){// check read permission
  1864.             except << "No read permission for File \"" << filename << "\"";
  1865.             throw GnuplotException( except.str() );
  1866.             return false;
  1867.         }
  1868.     }
  1869.     else{
  1870.         except << "File \"" << filename << "\" does not exist";
  1871.         throw GnuplotException( except.str() );
  1872.         return false;
  1873.     }
  1874. }
  1875.  
  1876.  
  1877.  
  1878. //------------------------------------------------------------------------------
  1879. //
  1880. // Opens a temporary file
  1881. //
  1882. std::string Gnuplot::create_tmpfile(std::ofstream &tmp)
  1883. {
  1884.  
  1885. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1886.     char name[] = "gnuplotiXXXXXX"; //tmp file in working directory
  1887. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1888.     char name[] = "/tmp/gnuplotiXXXXXX"; // tmp file in /tmp
  1889. #endif
  1890.  
  1891.     //
  1892.     // check if maximum number of temporary files reached
  1893.     //
  1894.     if (Gnuplot::tmpfile_num == GP_MAX_TMP_FILES - 1)
  1895.     {
  1896.         std::ostringstream except;
  1897.         except << "Maximum number of temporary files reached ("
  1898.                << GP_MAX_TMP_FILES << "): cannot open more files" << std::endl;
  1899.  
  1900.         throw GnuplotException( except.str() );
  1901.         return "";
  1902.     }
  1903.  
  1904.     // int mkstemp(char *name);
  1905.     // shall replace the contents of the string pointed to by "name" by a unique
  1906.     // filename, and return a file descriptor for the file open for reading and
  1907.     // writing.  Otherwise, -1 shall be returned if no suitable file could be
  1908.     // created.  The string in template should look like a filename with six
  1909.     // trailing 'X' s; mkstemp() replaces each 'X' with a character from the
  1910.     // portable filename character set.  The characters are chosen such that the
  1911.     // resulting name does not duplicate the name of an existing file at the
  1912.     // time of a call to mkstemp()
  1913.  
  1914.  
  1915.     //
  1916.     // open temporary files for output
  1917.     //
  1918. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1919.     if (_mktemp(name) == NULL)
  1920. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1921.     if (mkstemp(name) == -1)
  1922. #endif
  1923.     {
  1924.         std::ostringstream except;
  1925.         except << "Cannot create temporary file \"" << name << "\"";
  1926.         throw GnuplotException(except.str());
  1927.         return "";
  1928.     }
  1929.  
  1930.     tmp.open(name);
  1931.     if (tmp.bad())
  1932.     {
  1933.         std::ostringstream except;
  1934.         except << "Cannot create temporary file \"" << name << "\"";
  1935.         throw GnuplotException(except.str());
  1936.         return "";
  1937.     }
  1938.  
  1939.     //
  1940.     // Save the temporary filename
  1941.     //
  1942.     tmpfile_list.push_back(name);
  1943.     Gnuplot::tmpfile_num++;
  1944.  
  1945.     return name;
  1946. }
  1947.  
  1948. void Gnuplot::remove_tmpfiles(){
  1949.     if ((tmpfile_list).size() > 0)
  1950.     {
  1951.         for (unsigned int i = 0; i < tmpfile_list.size(); i++)
  1952.             remove( tmpfile_list[i].c_str() );
  1953.  
  1954.         Gnuplot::tmpfile_num -= tmpfile_list.size();
  1955.     }
  1956. }
  1957. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement