Skip to content

Latest commit

 

History

History
152 lines (93 loc) · 57 KB

CppGnuplotInterface.md

File metadata and controls

152 lines (93 loc) · 57 KB

 

 

 

 

 

 

STLQt CreatorLubuntu

 

GnuplotInterface is a class that enables the user to easily plot values in Gnuplot. It handles both the connection to Gnuplot and performs the window management as well. It creates a text-file in which the location of the Gnuplot executable can be entered (without recompiling the program).

 

The tool TestGnuplotInterface tests the GnuplotInterface class.

 


I only got this interface to work under MacOS

 

The one function that this class is built around is the popen function. This is a non-standard function to open a pipe. If this function is unknown under your programming environment, try either std::popen, std::_popen, std::__popen, popen, _popen or __popen.

 

 

 

 

 

 

 

Technical facts

 

 

 

 

 

 

./CppGnuplotInterface/CppGnuplotInterface.pri

 


INCLUDEPATH += \     ../../Classes/CppCanvas SOURCES += \     ../../Classes/CppCanvas/canvas.cpp HEADERS  += \     ../../Classes/CppCanvas/canvas.h OTHER_FILES += \     ../../Classes/CppCanvas/Licence.txt

 

 

 

 

 

./CppGnuplotInterface/gnuplotinterface.h

 


// //  Gnuplot - a C++ class interface with Gnuplot //  V4.0 // //  Created by Richel Bilderbeek on Fri Jun 10 2005. //  Open source. // //  Richel Bilderbeek //  Website: http://www.richelbilderbeek.nl // //  V4.0: 19th March 2008: Conformized code //  V3.0: 23th September 2006: Implemented suggestion by Christoph Schmalz. //                             According to Christoph it should work under Windows now. //                             Made the code 100% Standard C++. //  V2.0: 12th September 2005: Got program to compile under Windows environment. //                             Program is found NOT to run under Windows. //                             Somebody has an idea how to open Gnuplot.exe ??? //  V1.0: 10th June 2005: first version developed on Macintosh // // //  This class functions well at a Macintosh. Under Windows, the pipe to the //  Gnuplot executable (either MS-DOS or Windows executable) will not open. //  If you have an idea to solve this, please E-mail me. // // //  Feel free to contact me when: //  - YOU can get the program to run under Windows (and normally it wouldn't) //  - you encounter a compile error //  - you have made additional functionality //  - you have outsmarted me on this interface. // #ifndef __GNUPLOT_H #define __GNUPLOT_H #include <iostream> #include <string> #include <fstream> #include <sstream> #include <vector> #include <cstdio> #include <ctime> #include <cassert> enum GnuplotStyle {   styleLines,   stylePoints,   styleLinespoints,   styleImpulses,   styleDots,   styleSteps,   styleErrorbars,   styleBoxes,   styleBoxerrorbars, }; enum GnuplotTerminal {   terminalX11,   terminalAqua }; struct WindowData {   std::vector<std::string> tempFileName; }; struct Gnuplot {   Gnuplot();   ~Gnuplot();   void Execute(const std::string&) const;   void AddWindow(const int nWindows = 1);   void ChangeWindow(const int);   void SetTerminal(const GnuplotTerminal&);   void SetStyle(const GnuplotStyle&);   void SetYlabel(const std::string&);   void SetXlabel(const std::string&);   void Plot(const std::string &, const std::string& title = "y");   void Plot(const std::vector<double>&, const std::string& title = "y");   void Plot(const std::vector<double>&, const std::vector<double>&, const std::string& title = "data");   void Plot(const std::vector<double>&, const std::vector<double>&, const std::vector<double>&, const std::string& title = "z");   void EmptyPlot();   //Helper functions   void Sleep(const double) const;   const std::string Itoa(const int) const;   const std::string Ftoa(const double) const;   const bool FileExists(const std::string& fileName) const;   private:   std::FILE * mGnuPipe;   std::string mTerminal;   std::string mStyle;   std::vector<WindowData> mWindowData;   int mCurrentWindowNumber;   static int mTempFileNumber;   void SetLineStyles();   const std::string ReadFileName() const;   const std::string CreateTempFileName();   void CreateTempFile(const std::string&, const std::vector<double>&);   void CreateTempFile(const std::string&, const std::vector<double>&, const std::vector<double>&);   void CreateTempFile(const std::string&, const std::vector<double>&, const std::vector<double>&, const std::vector<double>&);   void PlotTempFile2D(const std::string&, const std::string&);   void PlotTempFile3D(const std::string&, const std::string&);   void Dot(const std::string& debugString = ".") const; }; #endif

 

 

 

 

 

./CppGnuplotInterface/gnuplotinterface.cpp

 


//--------------------------------------------------------------------------- // //  Gnuplot - a C++ class interface with Gnuplot //  V4.0 // //  Created by Richel Bilderbeek on Fri Jun 10 2005. //  Open source. // //  Richel Bilderbeek //  Website: http://www.richelbilderbeek.nl // //  V4.0: 19th March 2008: Conformized code //  V3.0: 23th September 2006: Implemented suggestion by Christoph Schmalz. //                             According to Christoph it should work under Windows now. //                             Made the code 100% Standard C++. //  V2.0: 12th September 2005: Got program to compile under Windows environment. //                             Program is found NOT to run under Windows. //                             Somebody has an idea how to open Gnuplot.exe ??? //  V1.0: 10th June 2005: first version developed on Macintosh // // //  This class functions well at a Macintosh. Under Windows, the pipe to the //  Gnuplot executable (either MS-DOS or Windows executable) will not open. //  If you have an idea to solve this, please E-mail me. // // //  Feel free to contact me when: //  - YOU can get the program to run under Windows (and normally it wouldn't) //  - you encounter a compile error //  - you have made additional functionality //  - you have outsmarted me on this interface. // //---------------------------------------------------------------------------------- #include "UnitGnuplotInterface.h" //---------------------------------------------------------------------------------- //#define EXTENSIVE_LOG //---------------------------------------------------------------------------------- int Gnuplot::mTempFileNumber = 0; //---------------------------------------------------------------------------------- Gnuplot::Gnuplot() : mGnuPipe(0), mTerminal("aqua"), mStyle("lines"), mCurrentWindowNumber(0) {   const std::string fileName = ReadFileName();   if (FileExists(fileName)==false)   {     std::cout       << "\nGnuplot file '" << fileName << "' does not exist."       << "\nTherefore, change the line in 'GnuplotLocation.txt"       << "\nto your Gnuplot location (e.g. 'c:/gnuplot/gnuplot')"       << "\nThis error is generated in line " << __LINE__       << "\nof file " << __FILE__ << std::endl       << "\n\nPress key to terminate program." << std::endl;     std::cin.get();     std::exit(1);   }   std::cout     << "Gnuplot executable found at '" << fileName << "'."     << "\nOpening pipe to Gnuplot" << std::endl;   mGnuPipe = std::_popen((fileName+" -persist").c_str(),"w"); //Changed 'rw' to 'w'   if (mGnuPipe==0)   {     std::cout << "Couldn't open connection to gnuplot" << std::endl;     std::cin.get();     std::exit(1);   }   SetLineStyles();   AddWindow();   ChangeWindow(0); } //---------------------------------------------------------------------------------- ///This reads the location of Gnuplot from the config file called GnuplotLocation.txt ///If it cannot find this file, it is created with a default value const std::string Gnuplot::ReadFileName() const {   const std::string fileName = "GnuplotLocation.txt";   std::string returnFileName;   if (FileExists(fileName)==true)   {     std::ifstream file(fileName.c_str());     assert(file.is_open()==true);     file >> returnFileName;     file.close();   }   else   {     std::ofstream file(fileName.c_str());     assert(file.is_open()==true);     returnFileName ="/sw/bin/gnuplot";     file << returnFileName << '\n';     file.close();   }   return returnFileName; } //---------------------------------------------------------------------------------- Gnuplot::~Gnuplot() {   const int nWindows = mWindowData.size();   for(int i=0; i!=nWindows; ++i)   {     mCurrentWindowNumber = i;     EmptyPlot();   }   if (_pclose(mGnuPipe) == -1) assert(!"Problem closing communication to Gnuplot"); } //---------------------------------------------------------------------------------- void Gnuplot::EmptyPlot() {   const int nPlots = mWindowData[mCurrentWindowNumber].tempFileName.size();   for (int i=0; i!=nPlots; ++i)   {     Dot("Removing file: " + mWindowData[mCurrentWindowNumber].tempFileName[i]);     std::remove(mWindowData[mCurrentWindowNumber].tempFileName[i].c_str());   } } //---------------------------------------------------------------------------------- void Gnuplot::SetTerminal(const GnuplotTerminal& terminal) {   switch(terminal)   {     case terminalAqua : mTerminal = "aqua"; break;     case terminalX11  : mTerminal = "x11" ; break;     default: assert(!"Unknown GnuplotTerminal");   } } //---------------------------------------------------------------------------------- void Gnuplot::SetStyle(const GnuplotStyle& style) {   switch(style)   {     case styleLines        : mStyle = "lines"; break;     case stylePoints       : mStyle = "points"; break;     case styleLinespoints  : mStyle = "linespoints"; break;     case styleImpulses     : mStyle = "impulses"; break;     case styleDots         : mStyle = "dots"; break;     case styleSteps        : mStyle = "steps"; break;     case styleErrorbars    : mStyle = "errorbars"; break;     case styleBoxes        : mStyle = "boxes"; break;     case styleBoxerrorbars : mStyle = "boxerrorbars"; break;     default: assert(!"Unknown GnuplotStyle");   } } //---------------------------------------------------------------------------------- void Gnuplot::Execute(const std::string& cmdstr) const {   Dot("Command sent to Gnuplot: " + static_cast<std::string>(cmdstr));   fputs((cmdstr+"\n").c_str(),mGnuPipe);   fflush(mGnuPipe);   Sleep(1.0); //Setting this sleep time too low results in errors } //---------------------------------------------------------------------------------- void Gnuplot::SetYlabel(const std::string& label) {   const std::string command = "set ylabel \""+label+"\"";   Execute(command.c_str()); } //---------------------------------------------------------------------------------- void Gnuplot::SetXlabel(const std::string& label) {   const std::string command = "set xlabel \""+label+"\"";   Execute(command.c_str()); } //---------------------------------------------------------------------------------- ///Change to plotting windows to 'windowNumber'. If this window number is beyond ///the amount of windows created, a new window will be created and that window ///will be set as the plotting window void Gnuplot::ChangeWindow(const int windowNumber) {   if (windowNumber==mCurrentWindowNumber) return;   if (windowNumber>= static_cast<int>(mWindowData.size()))   {     AddWindow();     mCurrentWindowNumber = mWindowData.size()-1;   }   else   {     mCurrentWindowNumber=windowNumber;   }   const std::string myCommand = "set terminal "+mTerminal+" "+Itoa(mCurrentWindowNumber+1);   Execute(myCommand.c_str()); } //---------------------------------------------------------------------------------- ///Creates an extra 'nWindows' display windows. void Gnuplot::AddWindow(const int nWindows) {   for (int i=0; i!=nWindows; ++i)   {     WindowData temp;     mWindowData.push_back(temp);   } } //---------------------------------------------------------------------------------- void Gnuplot::Plot(const std::string &equation, const std::string &title) {   std::string myCommand;   if (mWindowData[mCurrentWindowNumber].tempFileName.size() > 0)     myCommand = "replot " + equation + " title \"" + title + "\" with " + mStyle;   else     myCommand = "plot " + equation + " title \"" + title + "\" with " + mStyle;   Execute(myCommand.c_str()); } //---------------------------------------------------------------------------------- void Gnuplot::Plot(const std::vector<double>& x, const std::string &title) {   const std::string tempFileName = CreateTempFileName();   CreateTempFile(tempFileName,x);   PlotTempFile2D(tempFileName,title); } //---------------------------------------------------------------------------------- void Gnuplot::Plot(const std::vector<double>& x, const std::vector<double>& y, const std::string &title) {   const std::string tempFileName = CreateTempFileName();   CreateTempFile(tempFileName,x,y);   PlotTempFile2D(tempFileName,title); } //---------------------------------------------------------------------------------- void Gnuplot::Plot(const std::vector<double>& x, const std::vector<double>& y, const std::vector<double>& z, const std::string &title) {   const std::string tempFileName = CreateTempFileName();   CreateTempFile(tempFileName,x,y,z);   PlotTempFile3D(tempFileName,title); } //---------------------------------------------------------------------------------- void Gnuplot::PlotTempFile2D(const std::string& tempFileName, const std::string& title) {   std::string myCommand;   const int nSeries = mWindowData[mCurrentWindowNumber].tempFileName.size();   //Linestyles are nice, but don't work on my terminal...   ///if (nSeries>12) std::cout << "MAKE MORE LINESTYLES!!!" << std::endl;   //if ( nSeries == 0)   // myCommand = "plot \"" + tempFileName + "\" ls "+Itoa(nSerie)+" title \"" + title + "\" with " + mStyle;   //else   // myCommand = "replot \"" + tempFileName + "\" ls "+Itoa(nSerie)+" title \"" + title + "\" with " + mStyle;   if ( nSeries == 0)     myCommand = "plot \"" + tempFileName + "\" title \"" + title + "\" with " + mStyle;   else     myCommand = "replot \"" + tempFileName + "\" title \"" + title + "\" with " + mStyle;   Execute(myCommand.c_str());   Sleep(1.0); //Setting this sleep time too low results in errors   mWindowData[mCurrentWindowNumber].tempFileName.push_back(tempFileName); } //---------------------------------------------------------------------------------- void Gnuplot::PlotTempFile3D(const std::string& tempFileName, const std::string& title) {   //Does not work on my computer. Should be something like this...   Execute("set pm3d");   std::string myCommand;   if (mWindowData[mCurrentWindowNumber].tempFileName.size() == 0)     myCommand = "splot \"" + tempFileName + "\" title \"" + title + "\" with pm3d palette";   else     myCommand = "replot \"" + tempFileName + "\" title \"" + title + "\" with pm3d palette";   Execute(myCommand.c_str());   Sleep(1.0); //Setting this sleep time too low results in errors   mWindowData[mCurrentWindowNumber].tempFileName.push_back(tempFileName); } //---------------------------------------------------------------------------------- const std::string Gnuplot::CreateTempFileName() {   ++mTempFileNumber;   const std::string tempFileName = "GnuplotTemp"+Itoa(mTempFileNumber);   Dot("Created temp file '" + tempFileName);   return(tempFileName); } //---------------------------------------------------------------------------------- void Gnuplot::CreateTempFile(const std::string& tempFileName, const std::vector<double>& x) {   std::ofstream file(tempFileName.c_str());   assert(file.is_open()==true);   const int size = x.size();   for (int i = 0; i != size; i++) file << x[i] << std::endl;   file.close(); } //---------------------------------------------------------------------------------- void Gnuplot::CreateTempFile(const std::string& tempFileName, const std::vector<double>& x, const std::vector<double>& y) {   assert(x.size()==y.size());   std::ofstream file(tempFileName.c_str());   assert(file.is_open()==true);   const int size = x.size();   for (int i = 0; i != size; i++) file << x[i] << " " << y[i] << std::endl;   file.close(); } //---------------------------------------------------------------------------------- void Gnuplot::CreateTempFile(const std::string& tempFileName, const std::vector<double>& x, const std::vector<double>& y, const std::vector<double>& z) {   assert(x.size()==y.size());   assert(y.size()==z.size());   std::ofstream file(tempFileName.c_str());   assert(file.is_open()==true);   const int size = x.size();   for (int i = 0; i != size; i++) file << x[i] << " " << y[i] << " " << z[i] << std::endl;   file.close(); } //---------------------------------------------------------------------------------- void Gnuplot::SetLineStyles() {   //Does not work on all terminals. Like mine... :-(   //Execute("set style line  1 lt pal frac 0.0 lw 2");   //Execute("set style line  2 lt pal frac 0.0 lw 4");   //Execute("set style line  3 lt pal frac 0.2 lw 2");   //Execute("set style line  4 lt pal frac 0.2 lw 4");   //Execute("set style line  5 lt pal frac 0.4 lw 2");   //Execute("set style line  6 lt pal frac 0.4 lw 4");   //Execute("set style line  7 lt pal frac 0.6 lw 2");   //Execute("set style line  8 lt pal frac 0.6 lw 4");   //Execute("set style line  9 lt pal frac 0.8 lw 2");   //Execute("set style line 10 lt pal frac 0.8 lw 4");   //Execute("set style line 11 lt pal frac 1.0 lw 2");   //Execute("set style line 12 lt pal frac 1.0 lw 4"); } //---------------------------------------------------------------------------------- ///Logging when in developmental phase void Gnuplot::Dot(const std::string& debugString) const {   #ifdef EXTENSIVE_LOG   std::cout << "DOT: " << debugString << std::endl;   #endif } //---------------------------------------------------------------------------------- ///Wait for myTime seconds void Gnuplot::Sleep(const double myTime) const {   std::clock_t timeStart = std::clock();   std::clock_t timeEnd   = std::clock();   while ((std::difftime(timeEnd,timeStart) / CLK_TCK) < myTime)   {     //Wait...   } } //---------------------------------------------------------------------------------- ///Converts an integer to a string const std::string Gnuplot::Itoa(const int number) const {   std::ostringstream o;   if (!(o << number)) return "ERROR";   return o.str(); } //---------------------------------------------------------------------------------- ///Converts a double to a string const std::string Gnuplot::Ftoa(const double number) const {   std::ostringstream o;   if (!(o << number)) return "ERROR";   return o.str(); } //---------------------------------------------------------------------------------- ///Checks if a file exists const bool Gnuplot::FileExists(const std::string& fileName) const {   std::fstream fin;   fin.open(fileName.c_str(),std::ios::in);   if( fin.is_open() )   {     fin.close();     return true;   }   fin.close();   return false; } //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------