//---------------------------------------------------------------------------------- // Plots a 2d graph from a list of doubles: x y Gnuplot& Gnuplot::plot_xy(const std::vector<double> &x, const std::vector<double> &y, const std::string &title) { if (x.size() == 0 || y.size() == 0) { throw GnuplotException("std::vectors too small"); return *this; } if (x.size() != y.size()) { throw GnuplotException("Length of the std::vectors differs"); return *this; } std::ofstream tmp; std::string name = create_tmpfile(tmp); if (name == "") return *this; // write the data to file for (unsigned int i = 0; i < x.size(); i++) tmp << x[i] << " " << y[i] << std::endl; tmp.flush(); tmp.close(); this->plotfile_xy(name, 1, 2, title); return *this; }
Gnuplot& plot_xy_err(const X &x, const Y &y, const E &dy, const std::string &title = "") { if(x.size() == 0 || y.size() == 0 || dy.size() == 0) { throw GnuplotException("std::vectors too small"); return *this; } if(x.size() != y.size() || y.size() != dy.size()) { throw GnuplotException("Length of the std::vectors differs"); return *this; } std::ofstream tmp; std::string name = create_tmpfile(tmp); if(name == "") return *this; // // write the data to file // for (unsigned int i = 0; i < x.size(); i++) tmp << x[i] << " " << y[i] << " " << dy[i] << std::endl; tmp.flush(); tmp.close(); // Do the actual plot plotfile_xy_err(name, 1, 2, 3, title); return *this; };
//------------------------------------------------------------------------------ // // Opens up a gnuplot session, ready to receive commands // void Gnuplot::init() { // char * getenv ( const char * name ); get value of environment variable // Retrieves a C string containing the value of the environment variable // whose name is specified as argument. If the requested variable is not // part of the environment list, the function returns a NULL pointer. #if ( defined(unix) || defined(__unix) || defined(__unix__) ) && !defined(__APPLE__) if (getenv("DISPLAY") == NULL) { valid = false; throw GnuplotException("Can't find DISPLAY variable"); } #endif // if gnuplot not available if (!Gnuplot::get_program_path()) { valid = false; throw GnuplotException("Can't find gnuplot"); } // // open pipe // std::string tmp = Gnuplot::m_sGNUPlotPath + "/" + Gnuplot::m_sGNUPlotFileName; // FILE *popen(const char *command, const char *mode); // The popen() function shall execute the command specified by the string // command, create a pipe between the calling program and the executed // command, and return a pointer to a stream that can be used to either read // from or write to the pipe. #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) gnucmd = _popen(tmp.c_str(),"w"); #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) gnucmd = popen(tmp.c_str(),"w"); #endif // popen() shall return a pointer to an open stream that can be used to read // or write to the pipe. Otherwise, it shall return a null pointer and may // set errno to indicate the error. if (!gnucmd) { valid = false; throw GnuplotException("Couldn't open connection to gnuplot"); } nplots = 0; valid = true; smooth = ""; //set terminal type showonscreen(); return; }
//---------------------------------------------------------------------------------- // Opens a temporary file std::string Gnuplot::create_tmpfile(std::ofstream &tmp) { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) char name[] = "gnuplotiXXXXXX"; //tmp file in working directory #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) char name[] = "/tmp/gnuplotiXXXXXX"; // tmp file in /tmp #endif // check if maximum number of temporary files reached if (Gnuplot::tmpfile_num == GP_MAX_TMP_FILES - 1) { std::ostringstream except; except << "Maximum number of temporary files reached (" << GP_MAX_TMP_FILES << "): cannot open more files" << std::endl; throw GnuplotException( except.str() ); return ""; } // int mkstemp(char *name); // shall replace the contents of the string pointed to by "name" by a unique filename, // and return a file descriptor for the file open for reading and writing. // Otherwise, -1 shall be returned if no suitable file could be created. // The string in template should look like a filename with six trailing 'X' s; // mkstemp() replaces each 'X' with a character from the portable filename character set. // The characters are chosen such that the resulting name does not duplicate the name of an existing file at the time of a call to mkstemp() // open temporary files for output #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if (_mktemp(name) == nullptr) #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if (mkstemp(name) == -1) #endif { std::ostringstream except; except << "Cannot create temporary file \"" << name << "\""; throw GnuplotException(except.str()); return ""; } tmp.open(name); if (tmp.bad()) { std::ostringstream except; except << "Cannot create temporary file \"" << name << "\""; throw GnuplotException(except.str()); return ""; } // Save the temporary filename this->tmpfile_list.push_back(name); Gnuplot::tmpfile_num++; return name; }
//---------------------------------------------------------------------------------- // Find out if a command lives in m_sGNUPlotPath or in PATH bool Gnuplot::get_program_path() { // first look in m_sGNUPlotPath for Gnuplot std::string tmp = Gnuplot::m_sGNUPlotPath + "/" + Gnuplot::m_sGNUPlotNomeArquivo; #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if ( Gnuplot::file_exists(tmp,0) ) // check existence #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission #endif { return true; } // second look in PATH for Gnuplot char *path; // Retrieves a C string containing the value of the environment variable PATH path = getenv("PATH"); if (path == nullptr) { throw GnuplotException("Path is not set"); return false; } else { std::list<std::string> ls; //split path (one long string) into list ls of strings #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) stringtok(ls,path,";"); #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) stringtok(ls,path,":"); #endif // scan list for Gnuplot program files for (std::list<std::string>::const_iterator i = ls.begin(); i != ls.end(); ++i) { tmp = (*i) + "/" + Gnuplot::m_sGNUPlotNomeArquivo; #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if ( Gnuplot::file_exists(tmp,0) ) // check existence #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if ( Gnuplot::file_exists(tmp,1) ) // check existence and execution permission #endif { Gnuplot::m_sGNUPlotPath = *i; // set m_sGNUPlotPath return true; } } tmp = "Can't find gnuplot neither in PATH nor in \"" + Gnuplot::m_sGNUPlotPath + "\""; throw GnuplotException(tmp); Gnuplot::m_sGNUPlotPath = ""; return false; } }
//------------------------------------------------------------------------------ // // Destructor: needed to delete temporary files // Gnuplot::~Gnuplot() { // remove_tmpfiles(); // A stream opened by popen() should be closed by pclose() #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if (_pclose(gnucmd) == -1) #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if (pclose(gnucmd) == -1) #endif throw GnuplotException("Problem closing communication to gnuplot"); }
//------------------------------------------------------------------------------ // // define static member function: set standart terminal, used by showonscreen // defaults: Windows - win, Linux - x11, Mac - aqua // void Gnuplot::set_terminal_std(const std::string &type) { #if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if (type.find("x11") != std::string::npos && getenv("DISPLAY") == NULL) { throw GnuplotException("Can't find DISPLAY variable"); } #endif Gnuplot::terminal_std = type; return; }
//---------------------------------------------------------------------------------- // Destructor: needed to delete temporary files Gnuplot::~Gnuplot() { if ((this->tmpfile_list).size() > 0) { for (unsigned int i = 0; i < this->tmpfile_list.size(); i++) remove( this->tmpfile_list[i].c_str() ); Gnuplot::tmpfile_num -= this->tmpfile_list.size(); } // A stream opened by popen() should be closed by pclose() #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) if (_pclose(this->gnucmd) == -1) #elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) if (pclose(this->gnucmd) == -1) #endif throw GnuplotException("Problem closing communication to gnuplot"); }
//---------------------------------------------------------------------------------- // Plots a 2d graph from a list of doubles (x y) saved in a file Gnuplot& Gnuplot::plotfile_xy(const std::string &filename, const int column_x, const int column_y, const std::string &title) { // check if file exists if( !(Gnuplot::file_exists(filename,4)) ) // check existence and read permission { std::ostringstream except; if( !(Gnuplot::file_exists(filename,0)) ) // check existence except << "File \"" << filename << "\" does not exist"; else except << "No read permission for File \"" << filename << "\""; throw GnuplotException( except.str() ); return *this; } std::ostringstream cmdstr; // command to be sent to gnuplot if (this->nplots > 0 && this->two_dim == true) cmdstr << "replot "; else cmdstr << "plot "; cmdstr << "\"" << filename << "\" using " << column_x << ":" << column_y; if (title == "") cmdstr << " notitle "; else cmdstr << " title \"" << title << "\" "; if(smooth == "") cmdstr << "with " << this->pstyle; else cmdstr << "smooth " << this->smooth; // Do the actual plot this->cmd(cmdstr.str()); return *this; }