Advertisement
osipyonok

gnuplot_i.hpp

Feb 22nd, 2017
210
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 60.32 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 standart 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.     Gnuplot& plot_points(const std::string &plot,
  542.                          const std::string &params = "");
  543.  
  544.     /// plot an equation supplied as a std::string z=f(x,y), write only the function f(x,y) not z=
  545.     /// the independent variables have to be x and y
  546.     Gnuplot& plot_equation3d(const std::string &equation,
  547.                              const std::string &title = "");
  548.  
  549.  
  550.     /// plot image
  551.     Gnuplot& plot_image(const unsigned char *ucPicBuf,
  552.                         const unsigned int iWidth,
  553.                         const unsigned int iHeight,
  554.                         const std::string &title = "");
  555.  
  556.  
  557.     //----------------------------------------------------------------------------------
  558.     ///\brief replot repeats the last plot or splot command.
  559.     ///  this can be useful for viewing a plot with different set options,
  560.     ///  or when generating the same plot for several devices (showonscreen, savetops)
  561.     ///
  562.     /// \param ---
  563.     ///
  564.     /// \return ---
  565.     //----------------------------------------------------------------------------------
  566.     inline Gnuplot& replot(void){if (nplots > 0) cmd("replot");return *this;};
  567.  
  568.     /// resets a gnuplot session (next plot will erase previous ones)
  569.     Gnuplot& reset_plot();
  570.  
  571.     /// resets a gnuplot session and sets all variables to default
  572.     Gnuplot& reset_all();
  573.  
  574.     /// deletes temporary files
  575.     void remove_tmpfiles();
  576.  
  577.     // -------------------------------------------------------------------
  578.     /// \brief Is the gnuplot session valid ??
  579.     ///
  580.     ///
  581.     /// \param ---
  582.     ///
  583.     /// \return true if valid, false if not
  584.     // -------------------------------------------------------------------
  585.     inline bool is_valid(){return(valid);};
  586.  
  587. };
  588.  
  589. //------------------------------------------------------------------------------
  590. //
  591. // initialize static data
  592. //
  593. int Gnuplot::tmpfile_num = 0;
  594.  
  595. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  596. std::string Gnuplot::m_sGNUPlotFileName = "gnuplot.exe";
  597. std::string Gnuplot::m_sGNUPlotPath = "C:/program_files/gnuplot/bin/";
  598. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  599. std::string Gnuplot::m_sGNUPlotFileName = "gnuplot";
  600. std::string Gnuplot::m_sGNUPlotPath = "/usr/local/bin/";
  601. #endif
  602.  
  603. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  604. std::string Gnuplot::terminal_std = "windows";
  605. #elif ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__)
  606. std::string Gnuplot::terminal_std = "x11";
  607. #elif defined(__APPLE__)
  608. std::string Gnuplot::terminal_std = "aqua";
  609. #endif
  610.  
  611. //------------------------------------------------------------------------------
  612. //
  613. // constructor: set a style during construction
  614. //
  615. inline Gnuplot::Gnuplot(const std::string &style)
  616.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  617.  
  618. {
  619.     init();
  620.     set_style(style);
  621. }
  622.  
  623. //------------------------------------------------------------------------------
  624. //
  625. // constructor: open a new session, plot a signal (x)
  626. //
  627. inline Gnuplot::Gnuplot(const std::vector<double> &x,
  628.                  const std::string &title,
  629.                  const std::string &style,
  630.                  const std::string &labelx,
  631.                  const std::string &labely)
  632.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  633. {
  634.     init();
  635.  
  636.     set_style(style);
  637.     set_xlabel(labelx);
  638.     set_ylabel(labely);
  639.  
  640.     plot_x(x,title);
  641. }
  642.  
  643.  
  644. //------------------------------------------------------------------------------
  645. //
  646. // constructor: open a new session, plot a signal (x,y)
  647. //
  648. inline Gnuplot::Gnuplot(const std::vector<double> &x,
  649.                  const std::vector<double> &y,
  650.                  const std::string &title,
  651.                  const std::string &style,
  652.                  const std::string &labelx,
  653.                  const std::string &labely)
  654.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  655. {
  656.     init();
  657.  
  658.     set_style(style);
  659.     set_xlabel(labelx);
  660.     set_ylabel(labely);
  661.  
  662.     plot_xy(x,y,title);
  663. }
  664.  
  665.  
  666. //------------------------------------------------------------------------------
  667. //
  668. // constructor: open a new session, plot a signal (x,y,z)
  669. //
  670. inline Gnuplot::Gnuplot(const std::vector<double> &x,
  671.                  const std::vector<double> &y,
  672.                  const std::vector<double> &z,
  673.                  const std::string &title,
  674.                  const std::string &style,
  675.                  const std::string &labelx,
  676.                  const std::string &labely,
  677.                  const std::string &labelz)
  678.                :gnucmd(NULL) ,valid(false) ,two_dim(false) ,nplots(0)
  679. {
  680.     init();
  681.  
  682.     set_style(style);
  683.     set_xlabel(labelx);
  684.     set_ylabel(labely);
  685.     set_zlabel(labelz);
  686.  
  687.     plot_xyz(x,y,z,title);
  688. }
  689.  
  690.  
  691. //------------------------------------------------------------------------------
  692. //
  693. /// Plots a 2d graph from a list of doubles: x
  694. //
  695. template<typename X>
  696. Gnuplot& Gnuplot::plot_x(const X& x, const std::string &title)
  697. {
  698.     if (x.size() == 0)
  699.     {
  700.         throw GnuplotException("std::vector too small");
  701.         return *this;
  702.     }
  703.  
  704.     std::ofstream tmp;
  705.     std::string name = create_tmpfile(tmp);
  706.     if (name == "")
  707.         return *this;
  708.  
  709.     //
  710.     // write the data to file
  711.     //
  712.     for (unsigned int i = 0; i < x.size(); i++)
  713.         tmp << x[i] << std::endl;
  714.  
  715.     tmp.flush();
  716.     tmp.close();
  717.  
  718.  
  719.     plotfile_x(name, 1, title);
  720.  
  721.     return *this;
  722. }
  723.  
  724.  
  725. //------------------------------------------------------------------------------
  726. //
  727. /// Plots a 2d graph from a list of doubles: x y
  728. //
  729. template<typename X, typename Y>
  730. Gnuplot& Gnuplot::plot_xy(const X& x, const Y& y, const std::string &title)
  731. {
  732.     if (x.size() == 0 || y.size() == 0)
  733.     {
  734.         throw GnuplotException("std::vectors too small");
  735.         return *this;
  736.     }
  737.  
  738.     if (x.size() != y.size())
  739.     {
  740.         throw GnuplotException("Length of the std::vectors differs");
  741.         return *this;
  742.     }
  743.  
  744.  
  745.     std::ofstream tmp;
  746.     std::string name = create_tmpfile(tmp);
  747.     if (name == "")
  748.         return *this;
  749.  
  750.     //
  751.     // write the data to file
  752.     //
  753.     for (unsigned int i = 0; i < x.size(); i++)
  754.         tmp << x[i] << " " << y[i] << std::endl;
  755.  
  756.     tmp.flush();
  757.     tmp.close();
  758.  
  759.  
  760.     plotfile_xy(name, 1, 2, title);
  761.  
  762.     return *this;
  763. }
  764.  
  765. ///-----------------------------------------------------------------------------
  766. ///
  767. /// plot x,y pairs with dy errorbars
  768. ///
  769. template<typename X, typename Y, typename E>
  770. Gnuplot& Gnuplot::plot_xy_err(const X &x,
  771.                               const Y &y,
  772.                               const E &dy,
  773.                               const std::string &title)
  774. {
  775.     if (x.size() == 0 || y.size() == 0 || dy.size() == 0)
  776.     {
  777.         throw GnuplotException("std::vectors too small");
  778.         return *this;
  779.     }
  780.  
  781.     if (x.size() != y.size() || y.size() != dy.size())
  782.     {
  783.         throw GnuplotException("Length of the std::vectors differs");
  784.         return *this;
  785.     }
  786.  
  787.  
  788.     std::ofstream tmp;
  789.     std::string name = create_tmpfile(tmp);
  790.     if (name == "")
  791.         return *this;
  792.  
  793.     //
  794.     // write the data to file
  795.     //
  796.     for (unsigned int i = 0; i < x.size(); i++)
  797.         tmp << x[i] << " " << y[i] << " " << dy[i] << std::endl;
  798.  
  799.     tmp.flush();
  800.     tmp.close();
  801.  
  802.  
  803.     // Do the actual plot
  804.     plotfile_xy_err(name, 1, 2, 3, title);
  805.  
  806.     return *this;
  807. }
  808.  
  809.  
  810. //------------------------------------------------------------------------------
  811. //
  812. // Plots a 3d graph from a list of doubles: x y z
  813. //
  814. template<typename X, typename Y, typename Z>
  815. Gnuplot& Gnuplot::plot_xyz(const X &x,
  816.                            const Y &y,
  817.                            const Z &z,
  818.                            const std::string &title)
  819. {
  820.     if (x.size() == 0 || y.size() == 0 || z.size() == 0)
  821.     {
  822.         throw GnuplotException("std::vectors too small");
  823.         return *this;
  824.     }
  825.  
  826.     if (x.size() != y.size() || x.size() != z.size())
  827.     {
  828.         throw GnuplotException("Length of the std::vectors differs");
  829.         return *this;
  830.     }
  831.  
  832.  
  833.     std::ofstream tmp;
  834.     std::string name = create_tmpfile(tmp);
  835.     if (name == "")
  836.         return *this;
  837.  
  838.     //
  839.     // write the data to file
  840.     //
  841.     for (unsigned int i = 0; i < x.size(); i++)
  842.         tmp << x[i] << " " << y[i] << " " << z[i] <<std::endl;
  843.  
  844.     tmp.flush();
  845.     tmp.close();
  846.  
  847.  
  848.     plotfile_xyz(name, 1, 2, 3, title);
  849.  
  850.     return *this;
  851. }
  852.  
  853.  
  854. //------------------------------------------------------------------------------
  855. //
  856. // define static member function: set Gnuplot path manual
  857. //   for windows: path with slash '/' not backslash '\'
  858. //
  859. bool Gnuplot::set_GNUPlotPath(const std::string &path)
  860. {
  861.  
  862.     std::string tmp = path + "/" + Gnuplot::m_sGNUPlotFileName;
  863.  
  864.  
  865. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  866.     if ( Gnuplot::file_exists(tmp,0) ) // check existence
  867. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  868.     if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission
  869. #endif
  870.     {
  871.         Gnuplot::m_sGNUPlotPath = path;
  872.         return true;
  873.     }
  874.     else
  875.     {
  876.         Gnuplot::m_sGNUPlotPath.clear();
  877.         return false;
  878.     }
  879. }
  880.  
  881.  
  882. //------------------------------------------------------------------------------
  883. //
  884. // define static member function: set standart terminal, used by showonscreen
  885. //  defaults: Windows - win, Linux - x11, Mac - aqua
  886. //
  887. void Gnuplot::set_terminal_std(const std::string &type)
  888. {
  889. #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  890.     if (type.find("x11") != std::string::npos && getenv("DISPLAY") == NULL)
  891.     {
  892.         throw GnuplotException("Can't find DISPLAY variable");
  893.     }
  894. #endif
  895.  
  896.  
  897.     Gnuplot::terminal_std = type;
  898.     return;
  899. }
  900.  
  901.  
  902. //------------------------------------------------------------------------------
  903. //
  904. // A string tokenizer taken from http://www.sunsite.ualberta.ca/Documentation/
  905. // /Gnu/libstdc++-2.90.8/html/21_strings/stringtok_std_h.txt
  906. //
  907. template <typename Container>
  908. void stringtok (Container &container,
  909.                 std::string const &in,
  910.                 const char * const delimiters = " \t\n")
  911. {
  912.     const std::string::size_type len = in.length();
  913.           std::string::size_type i = 0;
  914.  
  915.     while ( i < len )
  916.     {
  917.         // eat leading whitespace
  918.         i = in.find_first_not_of (delimiters, i);
  919.  
  920.         if (i == std::string::npos)
  921.             return;   // nothing left but white space
  922.  
  923.         // find the end of the token
  924.         std::string::size_type j = in.find_first_of (delimiters, i);
  925.  
  926.         // push token
  927.         if (j == std::string::npos)
  928.         {
  929.             container.push_back (in.substr(i));
  930.             return;
  931.         }
  932.         else
  933.             container.push_back (in.substr(i, j-i));
  934.  
  935.         // set up for next loop
  936.         i = j + 1;
  937.     }
  938.  
  939.     return;
  940. }
  941.  
  942.  
  943. //------------------------------------------------------------------------------
  944. //
  945. // Destructor: needed to delete temporary files
  946. //
  947. Gnuplot::~Gnuplot()
  948. {
  949. //  remove_tmpfiles();
  950.  
  951.     // A stream opened by popen() should be closed by pclose()
  952. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  953.     if (_pclose(gnucmd) == -1)
  954. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  955.     if (pclose(gnucmd) == -1)
  956. #endif
  957.         throw GnuplotException("Problem closing communication to gnuplot");
  958. }
  959.  
  960.  
  961. //------------------------------------------------------------------------------
  962. //
  963. // Resets a gnuplot session (next plot will erase previous ones)
  964. //
  965. Gnuplot& Gnuplot::reset_plot()
  966. {
  967. //  remove_tmpfiles();
  968.  
  969.     nplots = 0;
  970.  
  971.     return *this;
  972. }
  973.  
  974.  
  975. //------------------------------------------------------------------------------
  976. //
  977. // resets a gnuplot session and sets all varibles to default
  978. //
  979. Gnuplot& Gnuplot::reset_all()
  980. {
  981. //  remove_tmpfiles();
  982.  
  983.     nplots = 0;
  984.     cmd("reset");
  985.     cmd("clear");
  986.     pstyle = "points";
  987.     smooth = "";
  988.     showonscreen();
  989.  
  990.     return *this;
  991. }
  992.  
  993.  
  994. //------------------------------------------------------------------------------
  995. //
  996. // Change the plotting style of a gnuplot session
  997. //
  998. Gnuplot& Gnuplot::set_style(const std::string &stylestr)
  999. {
  1000.     if (stylestr.find("lines")          == std::string::npos  &&
  1001.         stylestr.find("points")         == std::string::npos  &&
  1002.         stylestr.find("linespoints")    == std::string::npos  &&
  1003.         stylestr.find("impulses")       == std::string::npos  &&
  1004.         stylestr.find("dots")           == std::string::npos  &&
  1005.         stylestr.find("steps")          == std::string::npos  &&
  1006.         stylestr.find("fsteps")         == std::string::npos  &&
  1007.         stylestr.find("histeps")        == std::string::npos  &&
  1008.         stylestr.find("boxes")          == std::string::npos  &&  // 1-4 columns of data are required
  1009.         stylestr.find("filledcurves")   == std::string::npos  &&
  1010.         stylestr.find("histograms")     == std::string::npos  )   //only for one data column
  1011. //        stylestr.find("labels")         == std::string::npos  &&  // 3 columns of data are required
  1012. //        stylestr.find("xerrorbars")     == std::string::npos  &&  // 3-4 columns of data are required
  1013. //        stylestr.find("xerrorlines")    == std::string::npos  &&  // 3-4 columns of data are required
  1014. //        stylestr.find("errorbars")      == std::string::npos  &&  // 3-4 columns of data are required
  1015. //        stylestr.find("errorlines")     == std::string::npos  &&  // 3-4 columns of data are required
  1016. //        stylestr.find("yerrorbars")     == std::string::npos  &&  // 3-4 columns of data are required
  1017. //        stylestr.find("yerrorlines")    == std::string::npos  &&  // 3-4 columns of data are required
  1018. //        stylestr.find("boxerrorbars")   == std::string::npos  &&  // 3-5 columns of data are required
  1019. //        stylestr.find("xyerrorbars")    == std::string::npos  &&  // 4,6,7 columns of data are required
  1020. //        stylestr.find("xyerrorlines")   == std::string::npos  &&  // 4,6,7 columns of data are required
  1021. //        stylestr.find("boxxyerrorbars") == std::string::npos  &&  // 4,6,7 columns of data are required
  1022. //        stylestr.find("financebars")    == std::string::npos  &&  // 5 columns of data are required
  1023. //        stylestr.find("candlesticks")   == std::string::npos  &&  // 5 columns of data are required
  1024. //        stylestr.find("vectors")        == std::string::npos  &&
  1025. //        stylestr.find("image")          == std::string::npos  &&
  1026. //        stylestr.find("rgbimage")       == std::string::npos  &&
  1027. //        stylestr.find("pm3d")           == std::string::npos  )
  1028.     {
  1029.         pstyle = std::string("points");
  1030.     }
  1031.     else
  1032.     {
  1033.         pstyle = stylestr;
  1034.     }
  1035.  
  1036.     return *this;
  1037. }
  1038.  
  1039.  
  1040. //------------------------------------------------------------------------------
  1041. //
  1042. // smooth: interpolation and approximation of data
  1043. //
  1044. Gnuplot& Gnuplot::set_smooth(const std::string &stylestr)
  1045. {
  1046.     if (stylestr.find("unique")    == std::string::npos  &&
  1047.         stylestr.find("frequency") == std::string::npos  &&
  1048.         stylestr.find("csplines")  == std::string::npos  &&
  1049.         stylestr.find("acsplines") == std::string::npos  &&
  1050.         stylestr.find("bezier")    == std::string::npos  &&
  1051.         stylestr.find("sbezier")   == std::string::npos  )
  1052.     {
  1053.         smooth = "";
  1054.     }
  1055.     else
  1056.     {
  1057.         smooth = stylestr;
  1058.     }
  1059.  
  1060.     return *this;
  1061. }
  1062.  
  1063.  
  1064. //------------------------------------------------------------------------------
  1065. //
  1066. // sets terminal type to windows / x11
  1067. //
  1068. Gnuplot& Gnuplot::showonscreen()
  1069. {
  1070.     cmd("set output");
  1071.     cmd("set terminal " + Gnuplot::terminal_std);
  1072.  
  1073.     return *this;
  1074. }
  1075.  
  1076. //------------------------------------------------------------------------------
  1077. //
  1078. // saves a gnuplot session to a postscript file
  1079. //
  1080. Gnuplot& Gnuplot::savetops(const std::string &filename)
  1081. {
  1082.     cmd("set terminal postscript color");
  1083.  
  1084.     std::ostringstream cmdstr;
  1085.     cmdstr << "set output \"" << filename << ".ps\"";
  1086.     cmd(cmdstr.str());
  1087.  
  1088.     return *this;
  1089. }
  1090.  
  1091. //------------------------------------------------------------------------------
  1092. //
  1093. // Switches legend on
  1094. //
  1095. Gnuplot& Gnuplot::set_legend(const std::string &position)
  1096. {
  1097.     std::ostringstream cmdstr;
  1098.     cmdstr << "set key " << position;
  1099.  
  1100.     cmd(cmdstr.str());
  1101.  
  1102.     return *this;
  1103. }
  1104.  
  1105. //------------------------------------------------------------------------------
  1106. //
  1107. // turns on log scaling for the x axis
  1108. //
  1109. Gnuplot& Gnuplot::set_xlogscale(const double base)
  1110. {
  1111.     std::ostringstream cmdstr;
  1112.  
  1113.     cmdstr << "set logscale x " << base;
  1114.     cmd(cmdstr.str());
  1115.  
  1116.     return *this;
  1117. }
  1118.  
  1119. //------------------------------------------------------------------------------
  1120. //
  1121. // turns on log scaling for the y axis
  1122. //
  1123. Gnuplot& Gnuplot::set_ylogscale(const double base)
  1124. {
  1125.     std::ostringstream cmdstr;
  1126.  
  1127.     cmdstr << "set logscale y " << base;
  1128.     cmd(cmdstr.str());
  1129.  
  1130.     return *this;
  1131. }
  1132.  
  1133. //------------------------------------------------------------------------------
  1134. //
  1135. // turns on log scaling for the z axis
  1136. //
  1137. Gnuplot& Gnuplot::set_zlogscale(const double base)
  1138. {
  1139.     std::ostringstream cmdstr;
  1140.  
  1141.     cmdstr << "set logscale z " << base;
  1142.     cmd(cmdstr.str());
  1143.  
  1144.     return *this;
  1145. }
  1146.  
  1147. //------------------------------------------------------------------------------
  1148. //
  1149. // scales the size of the points used in plots
  1150. //
  1151. Gnuplot& Gnuplot::set_pointsize(const double pointsize)
  1152. {
  1153.     std::ostringstream cmdstr;
  1154.     cmdstr << "set pointsize " << pointsize;
  1155.     cmd(cmdstr.str());
  1156.  
  1157.     return *this;
  1158. }
  1159.  
  1160. //------------------------------------------------------------------------------
  1161. //
  1162. // set isoline density (grid) for plotting functions as surfaces
  1163. //
  1164. Gnuplot& Gnuplot::set_samples(const int samples)
  1165. {
  1166.     std::ostringstream cmdstr;
  1167.     cmdstr << "set samples " << samples;
  1168.     cmd(cmdstr.str());
  1169.  
  1170.     return *this;
  1171. }
  1172.  
  1173.  
  1174. //------------------------------------------------------------------------------
  1175. //
  1176. // set isoline density (grid) for plotting functions as surfaces
  1177. //
  1178. Gnuplot& Gnuplot::set_isosamples(const int isolines)
  1179. {
  1180.     std::ostringstream cmdstr;
  1181.     cmdstr << "set isosamples " << isolines;
  1182.     cmd(cmdstr.str());
  1183.  
  1184.     return *this;
  1185. }
  1186.  
  1187.  
  1188. //------------------------------------------------------------------------------
  1189. //
  1190. // enables contour drawing for surfaces set contour {base | surface | both}
  1191. //
  1192.  
  1193. Gnuplot& Gnuplot::set_contour(const std::string &position)
  1194. {
  1195.     if (position.find("base")    == std::string::npos  &&
  1196.         position.find("surface") == std::string::npos  &&
  1197.         position.find("both")    == std::string::npos  )
  1198.     {
  1199.         cmd("set contour base");
  1200.     }
  1201.     else
  1202.     {
  1203.         cmd("set contour " + position);
  1204.     }
  1205.  
  1206.     return *this;
  1207. }
  1208.  
  1209. //------------------------------------------------------------------------------
  1210. //
  1211. // set labels
  1212. //
  1213. // set the xlabel
  1214. Gnuplot& Gnuplot::set_xlabel(const std::string &label)
  1215. {
  1216.     std::ostringstream cmdstr;
  1217.  
  1218.     cmdstr << "set xlabel \"" << label << "\"";
  1219.     cmd(cmdstr.str());
  1220.  
  1221.     return *this;
  1222. }
  1223.  
  1224. //------------------------------------------------------------------------------
  1225. // set the ylabel
  1226. //
  1227. Gnuplot& Gnuplot::set_ylabel(const std::string &label)
  1228. {
  1229.     std::ostringstream cmdstr;
  1230.  
  1231.     cmdstr << "set ylabel \"" << label << "\"";
  1232.     cmd(cmdstr.str());
  1233.  
  1234.     return *this;
  1235. }
  1236.  
  1237. //------------------------------------------------------------------------------
  1238. // set the zlabel
  1239. //
  1240. Gnuplot& Gnuplot::set_zlabel(const std::string &label)
  1241. {
  1242.     std::ostringstream cmdstr;
  1243.  
  1244.     cmdstr << "set zlabel \"" << label << "\"";
  1245.     cmd(cmdstr.str());
  1246.  
  1247.     return *this;
  1248. }
  1249.  
  1250. //------------------------------------------------------------------------------
  1251. //
  1252. // set range
  1253. //
  1254. // set the xrange
  1255. Gnuplot& Gnuplot::set_xrange(const double iFrom,
  1256.                              const double iTo)
  1257. {
  1258.     std::ostringstream cmdstr;
  1259.  
  1260.     cmdstr << "set xrange[" << iFrom << ":" << iTo << "]";
  1261.     cmd(cmdstr.str());
  1262.  
  1263.     return *this;
  1264. }
  1265.  
  1266. //------------------------------------------------------------------------------
  1267. // set the yrange
  1268. //
  1269. Gnuplot& Gnuplot::set_yrange(const double iFrom,
  1270.                              const double iTo)
  1271. {
  1272.     std::ostringstream cmdstr;
  1273.  
  1274.     cmdstr << "set yrange[" << iFrom << ":" << iTo << "]";
  1275.     cmd(cmdstr.str());
  1276.  
  1277.     return *this;
  1278. }
  1279.  
  1280. //------------------------------------------------------------------------------
  1281. // set the zrange
  1282. //
  1283. Gnuplot& Gnuplot::set_zrange(const double iFrom,
  1284.                              const double iTo)
  1285. {
  1286.     std::ostringstream cmdstr;
  1287.  
  1288.     cmdstr << "set zrange[" << iFrom << ":" << iTo << "]";
  1289.     cmd(cmdstr.str());
  1290.  
  1291.     return *this;
  1292. }
  1293.  
  1294. //------------------------------------------------------------------------------
  1295. //
  1296. // set the palette range
  1297. //
  1298. Gnuplot& Gnuplot::set_cbrange(const double iFrom,
  1299.                               const double iTo)
  1300. {
  1301.     std::ostringstream cmdstr;
  1302.  
  1303.     cmdstr << "set cbrange[" << iFrom << ":" << iTo << "]";
  1304.     cmd(cmdstr.str());
  1305.  
  1306.     return *this;
  1307. }
  1308.  
  1309. //------------------------------------------------------------------------------
  1310. //
  1311. // Plots a linear equation y=ax+b (where you supply the
  1312. // slope a and intercept b)
  1313. //
  1314. Gnuplot& Gnuplot::plot_slope(const double a,
  1315.                              const double b,
  1316.                              const std::string &title)
  1317. {
  1318.     std::ostringstream cmdstr;
  1319.     //
  1320.     // command to be sent to gnuplot
  1321.     //
  1322.     if (nplots > 0  &&  two_dim == true)
  1323.         cmdstr << "replot ";
  1324.     else
  1325.         cmdstr << "plot ";
  1326.  
  1327.     cmdstr << a << " * x + " << b << " title \"";
  1328.  
  1329.     if (title == "")
  1330.         cmdstr << "f(x) = " << a << " * x + " << b;
  1331.     else
  1332.         cmdstr << title;
  1333.  
  1334.     cmdstr << "\" with " << pstyle;
  1335.  
  1336.     //
  1337.     // Do the actual plot
  1338.     //
  1339.     cmd(cmdstr.str());
  1340.  
  1341.     return *this;
  1342. }
  1343.  
  1344. //------------------------------------------------------------------------------
  1345. //
  1346. // Plot an equation supplied as a std::string y=f(x) (only f(x) expected)
  1347. //
  1348. Gnuplot& Gnuplot::plot_equation(const std::string &equation,
  1349.                                 const std::string &title)
  1350. {
  1351.     std::ostringstream cmdstr;
  1352.     //
  1353.     // command to be sent to gnuplot
  1354.     //
  1355.     if (nplots > 0  &&  two_dim == true)
  1356.         cmdstr << "replot ";
  1357.     else
  1358.         cmdstr << "plot ";
  1359.  
  1360.     cmdstr << equation << " title \"";
  1361.  
  1362.     if (title == "")
  1363.         cmdstr << "f(x) = " << equation;
  1364.     else
  1365.         cmdstr << title;
  1366.  
  1367.     cmdstr << "\" with " << pstyle;
  1368.  
  1369.     //
  1370.     // Do the actual plot
  1371.     //
  1372.     cmd(cmdstr.str());
  1373.  
  1374.     return *this;
  1375. }
  1376.  
  1377. Gnuplot& Gnuplot::plot_points(const std::string &plot,
  1378.                          const std::string &params){                     
  1379.      std::ostringstream cmdstr;
  1380.      if(params.length() > 0){
  1381.          cmdstr << params << std::endl;
  1382.      }
  1383.      cmdstr << plot << std::endl;
  1384.      cmd(cmdstr.str());
  1385.      return *this;
  1386. }
  1387. //------------------------------------------------------------------------------
  1388. //
  1389. // plot an equation supplied as a std::string y=(x)
  1390. //
  1391. Gnuplot& Gnuplot::plot_equation3d(const std::string &equation,
  1392.                                   const std::string &title)
  1393. {
  1394.     std::ostringstream cmdstr;
  1395.     //
  1396.     // command to be sent to gnuplot
  1397.     //
  1398.     if (nplots > 0  &&  two_dim == false)
  1399.         cmdstr << "replot ";
  1400.     else
  1401.         cmdstr << "splot ";
  1402.  
  1403.     cmdstr << equation << " title \"";
  1404.  
  1405.     if (title == "")
  1406.         cmdstr << "f(x,y) = " << equation;
  1407.     else
  1408.         cmdstr << title;
  1409.  
  1410.     cmdstr << "\" with " << pstyle;
  1411.  
  1412.     //
  1413.     // Do the actual plot
  1414.     //
  1415.     cmd(cmdstr.str());
  1416.  
  1417.     return *this;
  1418. }
  1419.  
  1420.  
  1421. //------------------------------------------------------------------------------
  1422. //
  1423. // Plots a 2d graph from a list of doubles (x) saved in a file
  1424. //
  1425. Gnuplot& Gnuplot::plotfile_x(const std::string &filename,
  1426.                              const unsigned int column,
  1427.                              const std::string &title)
  1428. {
  1429.     //
  1430.     // check if file exists
  1431.     //
  1432.     file_available(filename);
  1433.  
  1434.  
  1435.     std::ostringstream cmdstr;
  1436.     //
  1437.     // command to be sent to gnuplot
  1438.     //
  1439.     if (nplots > 0  &&  two_dim == true)
  1440.         cmdstr << "replot ";
  1441.     else
  1442.         cmdstr << "plot ";
  1443.  
  1444.     cmdstr << "\"" << filename << "\" using " << column;
  1445.  
  1446.     if (title == "")
  1447.         cmdstr << " notitle ";
  1448.     else
  1449.         cmdstr << " title \"" << title << "\" ";
  1450.  
  1451.     if(smooth == "")
  1452.         cmdstr << "with " << pstyle;
  1453.     else
  1454.         cmdstr << "smooth " << smooth;
  1455.  
  1456.     //
  1457.     // Do the actual plot
  1458.     //
  1459.     cmd(cmdstr.str()); //nplots++; two_dim = true;  already in cmd();
  1460.  
  1461.     return *this;
  1462. }
  1463.  
  1464.  
  1465.  
  1466. //------------------------------------------------------------------------------
  1467. //
  1468. // Plots a 2d graph from a list of doubles (x y) saved in a file
  1469. //
  1470. Gnuplot& Gnuplot::plotfile_xy(const std::string &filename,
  1471.                               const unsigned int column_x,
  1472.                               const unsigned int column_y,
  1473.                               const std::string &title)
  1474. {
  1475.     //
  1476.     // check if file exists
  1477.     //
  1478.     file_available(filename);
  1479.  
  1480.  
  1481.     std::ostringstream cmdstr;
  1482.     //
  1483.     // command to be sent to gnuplot
  1484.     //
  1485.     if (nplots > 0  &&  two_dim == true)
  1486.         cmdstr << "replot ";
  1487.     else
  1488.         cmdstr << "plot ";
  1489.  
  1490.     cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y;
  1491.  
  1492.     if (title == "")
  1493.         cmdstr << " notitle ";
  1494.     else
  1495.         cmdstr << " title \"" << title << "\" ";
  1496.  
  1497.     if(smooth == "")
  1498.         cmdstr << "with " << pstyle;
  1499.     else
  1500.         cmdstr << "smooth " << smooth;
  1501.  
  1502.     //
  1503.     // Do the actual plot
  1504.     //
  1505.     cmd(cmdstr.str());
  1506.  
  1507.     return *this;
  1508. }
  1509.  
  1510.  
  1511. //------------------------------------------------------------------------------
  1512. //
  1513. // Plots a 2d graph with errorbars from a list of doubles (x y dy) in a file
  1514. //
  1515. Gnuplot& Gnuplot::plotfile_xy_err(const std::string &filename,
  1516.                                   const unsigned int column_x,
  1517.                                   const unsigned int column_y,
  1518.                                   const unsigned int column_dy,
  1519.                                   const std::string &title)
  1520. {
  1521.     //
  1522.     // check if file exists
  1523.     //
  1524.     file_available(filename);
  1525.  
  1526.     std::ostringstream cmdstr;
  1527.     //
  1528.     // command to be sent to gnuplot
  1529.     //
  1530.     if (nplots > 0  &&  two_dim == true)
  1531.         cmdstr << "replot ";
  1532.     else
  1533.         cmdstr << "plot ";
  1534.  
  1535.     cmdstr << "\"" << filename << "\" using "
  1536.            << column_x << ":" << column_y << ":" << column_dy
  1537.            << " with errorbars ";
  1538.  
  1539.     if (title == "")
  1540.         cmdstr << " notitle ";
  1541.     else
  1542.         cmdstr << " title \"" << title << "\" ";
  1543.  
  1544.     //
  1545.     // Do the actual plot
  1546.     //
  1547.     cmd(cmdstr.str());
  1548.  
  1549.     return *this;
  1550. }
  1551.  
  1552.  
  1553. //------------------------------------------------------------------------------
  1554. //
  1555. // Plots a 3d graph from a list of doubles (x y z) saved in a file
  1556. //
  1557. Gnuplot& Gnuplot::plotfile_xyz(const std::string &filename,
  1558.                                const unsigned int column_x,
  1559.                                const unsigned int column_y,
  1560.                                const unsigned int column_z,
  1561.                                const std::string &title)
  1562. {
  1563.     //
  1564.     // check if file exists
  1565.     //
  1566.     file_available(filename);
  1567.  
  1568.     std::ostringstream cmdstr;
  1569.     //
  1570.     // command to be sent to gnuplot
  1571.     //
  1572.     if (nplots > 0  &&  two_dim == false)
  1573.         cmdstr << "replot ";
  1574.     else
  1575.         cmdstr << "splot ";
  1576.  
  1577.     cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y
  1578.            << ":" << column_z;
  1579.  
  1580.     if (title == "")
  1581.         cmdstr << " notitle with " << pstyle;
  1582.     else
  1583.         cmdstr << " title \"" << title << "\" with " << pstyle;
  1584.  
  1585.     //
  1586.     // Do the actual plot
  1587.     //
  1588.     cmd(cmdstr.str());
  1589.  
  1590.     return *this;
  1591. }
  1592.  
  1593.  
  1594.  
  1595. //------------------------------------------------------------------------------
  1596. //
  1597. /// *  note that this function is not valid for versions of GNUPlot below 4.2
  1598. //
  1599. Gnuplot& Gnuplot::plot_image(const unsigned char * ucPicBuf,
  1600.                              const unsigned int iWidth,
  1601.                              const unsigned int iHeight,
  1602.                              const std::string &title)
  1603. {
  1604.     std::ofstream tmp;
  1605.     std::string name = create_tmpfile(tmp);
  1606.     if (name == "")
  1607.         return *this;
  1608.  
  1609.     //
  1610.     // write the data to file
  1611.     //
  1612.     int iIndex = 0;
  1613.     for(int iRow = 0; iRow < iHeight; iRow++)
  1614.     {
  1615.         for(int iColumn = 0; iColumn < iWidth; iColumn++)
  1616.         {
  1617.             tmp << iColumn << " " << iRow  << " "
  1618.                 << static_cast<float>(ucPicBuf[iIndex++]) << std::endl;
  1619.         }
  1620.     }
  1621.  
  1622.     tmp.flush();
  1623.     tmp.close();
  1624.  
  1625.  
  1626.     std::ostringstream cmdstr;
  1627.     //
  1628.     // command to be sent to gnuplot
  1629.     //
  1630.     if (nplots > 0  &&  two_dim == true)
  1631.         cmdstr << "replot ";
  1632.     else
  1633.         cmdstr << "plot ";
  1634.  
  1635.     if (title == "")
  1636.         cmdstr << "\"" << name << "\" with image";
  1637.     else
  1638.         cmdstr << "\"" << name << "\" title \"" << title << "\" with image";
  1639.  
  1640.     //
  1641.     // Do the actual plot
  1642.     //
  1643.     cmd(cmdstr.str());
  1644.  
  1645.     return *this;
  1646. }
  1647.  
  1648.  
  1649.  
  1650. //------------------------------------------------------------------------------
  1651. //
  1652. // Sends a command to an active gnuplot session
  1653. //
  1654. Gnuplot& Gnuplot::cmd(const std::string &cmdstr)
  1655. {
  1656.     if( !(valid) )
  1657.     {
  1658.         return *this;
  1659.     }
  1660.  
  1661.  
  1662.     // int fputs ( const char * str, FILE * stream );
  1663.     // writes the string str to the stream.
  1664.     // The function begins copying from the address specified (str) until it
  1665.     // reaches the terminating null character ('\0'). This final
  1666.     // null-character is not copied to the stream.
  1667.     fputs( (cmdstr+"\n").c_str(), gnucmd );
  1668.  
  1669.     // int fflush ( FILE * stream );
  1670.     // If the given stream was open for writing and the last i/o operation was
  1671.     // an output operation, any unwritten data in the output buffer is written
  1672.     // to the file.  If the argument is a null pointer, all open files are
  1673.     // flushed.  The stream remains open after this call.
  1674.     fflush(gnucmd);
  1675.  
  1676.  
  1677.     if( cmdstr.find("replot") != std::string::npos )
  1678.     {
  1679.         return *this;
  1680.     }
  1681.     else if( cmdstr.find("splot") != std::string::npos )
  1682.     {
  1683.         two_dim = false;
  1684.         nplots++;
  1685.     }
  1686.     else if( cmdstr.find("plot") != std::string::npos )
  1687.     {
  1688.         two_dim = true;
  1689.         nplots++;
  1690.     }
  1691.  
  1692.     return *this;
  1693. }
  1694.  
  1695.  
  1696.  
  1697. //------------------------------------------------------------------------------
  1698. //
  1699. // Opens up a gnuplot session, ready to receive commands
  1700. //
  1701. void Gnuplot::init()
  1702. {
  1703.     // char * getenv ( const char * name );  get value of environment variable
  1704.     // Retrieves a C string containing the value of the environment variable
  1705.     // whose name is specified as argument.  If the requested variable is not
  1706.     // part of the environment list, the function returns a NULL pointer.
  1707. #if ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__)
  1708.     if (getenv("DISPLAY") == NULL)
  1709.     {
  1710.         valid = false;
  1711.         throw GnuplotException("Can't find DISPLAY variable");
  1712.     }
  1713. #endif
  1714.  
  1715.  
  1716.     // if gnuplot not available
  1717.     if (!Gnuplot::get_program_path())
  1718.     {
  1719.         valid = false;
  1720.         throw GnuplotException("Can't find gnuplot");
  1721.     }
  1722.  
  1723.  
  1724.     //
  1725.     // open pipe
  1726.     //
  1727.     std::string tmp = std::string("\"") + Gnuplot::m_sGNUPlotPath + "/" +
  1728.         Gnuplot::m_sGNUPlotFileName + std::string("\"");
  1729.     // FILE *popen(const char *command, const char *mode);
  1730.     // The popen() function shall execute the command specified by the string
  1731.     // command, create a pipe between the calling program and the executed
  1732.     // command, and return a pointer to a stream that can be used to either read
  1733.     // from or write to the pipe.
  1734. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1735.     gnucmd = _popen(tmp.c_str(),"w");
  1736. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1737.     gnucmd = popen(tmp.c_str(),"w");
  1738. #endif
  1739.  
  1740.     // popen() shall return a pointer to an open stream that can be used to read
  1741.     // or write to the pipe.  Otherwise, it shall return a null pointer and may
  1742.     // set errno to indicate the error.
  1743.     if (!gnucmd)
  1744.     {
  1745.         valid = false;
  1746.         throw GnuplotException("Couldn't open connection to gnuplot");
  1747.     }
  1748.  
  1749.     nplots = 0;
  1750.     valid = true;
  1751.     smooth = "";
  1752.  
  1753.     //set terminal type
  1754.     showonscreen();
  1755.  
  1756.     return;
  1757. }
  1758.  
  1759.  
  1760. //------------------------------------------------------------------------------
  1761. //
  1762. // Find out if a command lives in m_sGNUPlotPath or in PATH
  1763. //
  1764. bool Gnuplot::get_program_path()
  1765. {
  1766.     //
  1767.     // first look in m_sGNUPlotPath for Gnuplot
  1768.     //
  1769.     std::string tmp = Gnuplot::m_sGNUPlotPath + "/" +
  1770.         Gnuplot::m_sGNUPlotFileName;
  1771.  
  1772. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1773.     if ( Gnuplot::file_exists(tmp,0) ) // check existence
  1774. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1775.     if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission
  1776. #endif
  1777.     {
  1778.         return true;
  1779.     }
  1780.  
  1781.  
  1782.     //
  1783.     // second look in PATH for Gnuplot
  1784.     //
  1785.     char *path;
  1786.     // Retrieves a C string containing the value of environment variable PATH
  1787.     path = getenv("PATH");
  1788.  
  1789.  
  1790.     if (path == NULL)
  1791.     {
  1792.         throw GnuplotException("Path is not set");
  1793.         return false;
  1794.     }
  1795.     else
  1796.     {
  1797.         std::list<std::string> ls;
  1798.  
  1799.         //split path (one long string) into list ls of strings
  1800. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1801.         stringtok(ls,path,";");
  1802. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1803.         stringtok(ls,path,":");
  1804. #endif
  1805.  
  1806.         // scan list for Gnuplot program files
  1807.         for (std::list<std::string>::const_iterator i = ls.begin();
  1808.                 i != ls.end(); ++i)
  1809.         {
  1810.             tmp = (*i) + "/" + Gnuplot::m_sGNUPlotFileName;
  1811. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1812.             if ( Gnuplot::file_exists(tmp,0) ) // check existence
  1813. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1814.             if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission
  1815. #endif
  1816.             {
  1817.                 Gnuplot::m_sGNUPlotPath = *i; // set m_sGNUPlotPath
  1818.                 return true;
  1819.             }
  1820.         }
  1821.  
  1822.         tmp = "Can't find gnuplot neither in PATH nor in \"" +
  1823.             Gnuplot::m_sGNUPlotPath + "\"";
  1824.         throw GnuplotException(tmp);
  1825.  
  1826.         Gnuplot::m_sGNUPlotPath = "";
  1827.         return false;
  1828.     }
  1829. }
  1830.  
  1831.  
  1832.  
  1833. //------------------------------------------------------------------------------
  1834. //
  1835. // check if file exists
  1836. //
  1837. bool Gnuplot::file_exists(const std::string &filename, int mode)
  1838. {
  1839.     if ( mode < 0 || mode > 7)
  1840.     {
  1841.         throw std::runtime_error("In function \"Gnuplot::file_exists\": mode\
  1842.                has to be an integer between 0 and 7");
  1843.         return false;
  1844.     }
  1845.  
  1846.     // int _access(const char *path, int mode);
  1847.     //  returns 0 if the file has the given mode,
  1848.     //  it returns -1 if the named file does not exist or is not accessible in
  1849.     //  the given mode
  1850.     // mode = 0 (F_OK) (default): checks file for existence only
  1851.     // mode = 1 (X_OK): execution permission
  1852.     // mode = 2 (W_OK): write permission
  1853.     // mode = 4 (R_OK): read permission
  1854.     // mode = 6       : read and write permission
  1855.     // mode = 7       : read, write and execution permission
  1856. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1857.     if (_access(filename.c_str(), mode) == 0)
  1858. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1859.     if (access(filename.c_str(), mode) == 0)
  1860. #endif
  1861.     {
  1862.         return true;
  1863.     }
  1864.     else
  1865.     {
  1866.         return false;
  1867.     }
  1868.  
  1869. }
  1870.  
  1871. bool Gnuplot::file_available(const std::string &filename){
  1872.     std::ostringstream except;
  1873.     if( Gnuplot::file_exists(filename,0) ) // check existence
  1874.     {
  1875.         if( !(Gnuplot::file_exists(filename,4)) ){// check read permission
  1876.             except << "No read permission for File \"" << filename << "\"";
  1877.             throw GnuplotException( except.str() );
  1878.             return false;
  1879.         }
  1880.     }
  1881.     else{
  1882.         except << "File \"" << filename << "\" does not exist";
  1883.         throw GnuplotException( except.str() );
  1884.         return false;
  1885.     }
  1886. }
  1887.  
  1888.  
  1889.  
  1890. //------------------------------------------------------------------------------
  1891. //
  1892. // Opens a temporary file
  1893. //
  1894. std::string Gnuplot::create_tmpfile(std::ofstream &tmp)
  1895. {
  1896.  
  1897. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1898.     char name[] = "gnuplotiXXXXXX"; //tmp file in working directory
  1899. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1900.     char name[] = "/tmp/gnuplotiXXXXXX"; // tmp file in /tmp
  1901. #endif
  1902.  
  1903.     //
  1904.     // check if maximum number of temporary files reached
  1905.     //
  1906.     if (Gnuplot::tmpfile_num == GP_MAX_TMP_FILES - 1)
  1907.     {
  1908.         std::ostringstream except;
  1909.         except << "Maximum number of temporary files reached ("
  1910.                << GP_MAX_TMP_FILES << "): cannot open more files" << std::endl;
  1911.  
  1912.         throw GnuplotException( except.str() );
  1913.         return "";
  1914.     }
  1915.  
  1916.     // int mkstemp(char *name);
  1917.     // shall replace the contents of the string pointed to by "name" by a unique
  1918.     // filename, and return a file descriptor for the file open for reading and
  1919.     // writing.  Otherwise, -1 shall be returned if no suitable file could be
  1920.     // created.  The string in template should look like a filename with six
  1921.     // trailing 'X' s; mkstemp() replaces each 'X' with a character from the
  1922.     // portable filename character set.  The characters are chosen such that the
  1923.     // resulting name does not duplicate the name of an existing file at the
  1924.     // time of a call to mkstemp()
  1925.  
  1926.  
  1927.     //
  1928.     // open temporary files for output
  1929.     //
  1930. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
  1931.     if (_mktemp(name) == NULL)
  1932. #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
  1933.     if (mkstemp(name) == -1)
  1934. #endif
  1935.     {
  1936.         std::ostringstream except;
  1937.         except << "Cannot create temporary file \"" << name << "\"";
  1938.         throw GnuplotException(except.str());
  1939.         return "";
  1940.     }
  1941.  
  1942.     tmp.open(name);
  1943.     if (tmp.bad())
  1944.     {
  1945.         std::ostringstream except;
  1946.         except << "Cannot create temporary file \"" << name << "\"";
  1947.         throw GnuplotException(except.str());
  1948.         return "";
  1949.     }
  1950.  
  1951.     //
  1952.     // Save the temporary filename
  1953.     //
  1954.     tmpfile_list.push_back(name);
  1955.     Gnuplot::tmpfile_num++;
  1956.  
  1957.     return name;
  1958. }
  1959.  
  1960. void Gnuplot::remove_tmpfiles(){
  1961.     if ((tmpfile_list).size() > 0)
  1962.     {
  1963.         for (unsigned int i = 0; i < tmpfile_list.size(); i++)
  1964.             remove( tmpfile_list[i].c_str() );
  1965.  
  1966.         Gnuplot::tmpfile_num -= tmpfile_list.size();
  1967.     }
  1968. }
  1969. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement