123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675 |
- ////////////////////////////////////////////
- //
- // A C++ interface to gnuplot.
- //
- // This is a direct translation from the C interface
- // written by N. Devillard (which is available from
- // http://ndevilla.free.fr/gnuplot/).
- //
- // As in the C interface this uses pipes and so wont
- // run on a system that does'nt have POSIX pipe
- // support
- //
- // Rajarshi Guha
- // <rajarshi@presidency.com>
- //
- // 07/03/03
- //
- ////////////////////////////////////////////
- #include "vislearning/baselib/Gnuplot.h"
- using namespace OBJREC;
- #define PATH_MAXNAMESZ 4096
- using namespace std;
- /////////////////////////////
- //
- // A string tokenizer taken from
- // http://www.sunsite.ualberta.ca/Documentation/Gnu/libstdc++-2.90.8/html/21_strings/stringtok_std_h.txt
- //
- /////////////////////////////
- template<typename Container>
- void stringtok(Container &container, std::string const &in,
- const char * const delimiters = " \t\n")
- {
- const string::size_type len = in.length();
- string::size_type i = 0;
- while (i < len)
- {
- // eat leading whitespace
- i = in.find_first_not_of(delimiters, i);
- if (i == string::npos)
- return; // nothing left but white space
- // find the end of the token
- string::size_type j = in.find_first_of(delimiters, i);
- // push token
- if (j == string::npos)
- {
- container.push_back(in.substr(i));
- return;
- }
- else
- container.push_back(in.substr(i, j - i));
- // set up for next loop
- i = j + 1;
- }
- }
- //
- // Constructors
- //
- Gnuplot::Gnuplot(void)
- {
- checkSystemVariablesOpenGnuplotCommand();
- this->set_style("points");
- }
- Gnuplot::Gnuplot(const std::string &style)
- {
- checkSystemVariablesOpenGnuplotCommand();
- this->set_style(style);
- }
- Gnuplot::Gnuplot(const std::string &title, const std::string &style,
- const std::string &labelx, const std::string &labely, vector<double> x,
- vector<double> y)
- {
- checkSystemVariablesOpenGnuplotCommand();
- if (x.size() == 0 || y.size() == 0)
- throw GnuplotException("vectors too small");
- if (style == "")
- this->set_style("lines");
- else
- this->set_style(style);
- if (labelx == "")
- this->set_xlabel("X");
- else
- this->set_xlabel(labelx);
- if (labely == "")
- this->set_ylabel("Y");
- else
- this->set_ylabel(labely);
- this->plot_xy(x, y, title);
- cout << "Press enter to continue" << endl;
- while (getchar() != '\n')
- {
- }
- }
- Gnuplot::Gnuplot(const std::string &title, const std::string &style,
- const std::string &labelx, const std::string &labely, vector<double> x)
- {
- checkSystemVariablesOpenGnuplotCommand();
- if (x.size() == 0)
- throw GnuplotException("vector too small");
- if (!this->gnucmd)
- throw GnuplotException("Could'nt open connection to gnuplot");
- if (style == "")
- this->set_style("lines");
- else
- this->set_style(style);
- if (labelx == "")
- this->set_xlabel("X");
- else
- this->set_xlabel(labelx);
- if (labely == "")
- this->set_ylabel("Y");
- else
- this->set_ylabel(labely);
- this->plot_x(x, title);
- cout << "Press enter to continue" << endl;
- while (getchar() != '\n')
- {
- }
- }
- void Gnuplot::checkSystemVariablesOpenGnuplotCommand()
- {
- if (!this->get_program_path("gnuplot"))
- {
- this->valid = false;
- throw GnuplotException("Can't find gnuplot in your PATH");
- }
- this->gnucmd = popen("gnuplot", "w");
- if (!this->gnucmd)
- {
- this->valid = false;
- throw GnuplotException("Could'nt open connection to gnuplot");
- }
- if (getenv("DISPLAY") == NULL)
- {
- if (this->gnucmd)
- {
- fprintf(stderr, "no Display found, changing to Terminal PNG\n");
- setFileOutput("png", "gnuplot_automatic_tmp_image.png");
- }
- }
- this->nplots = 0;
- this->valid = true;
- }
- Gnuplot::~Gnuplot()
- {
- if (pclose(this->gnucmd) == -1)
- cerr << "Problem closing communication to gnuplot" << endl;
- if ((this->to_delete).size() > 0)
- {
- for (vector<string>::size_type i = 0; i < this->to_delete.size(); i++)
- remove(this->to_delete[i].c_str());
- to_delete.clear();
- }
- return;
- }
- bool Gnuplot::is_valid(void)
- {
- return (this->valid);
- }
- bool Gnuplot::get_program_path(const std::string pname)
- {
- list<string> ls;
- char *path;
- path = getenv("PATH");
- if (!path)
- {
- cerr << "Path is not set" << endl;
- return false;
- }
- else
- {
- stringtok(ls, path, ":");
- for (list<string>::const_iterator i = ls.begin(); i != ls.end(); ++i)
- {
- std::string tmp = (*i) + "/" + pname;
- if (access(tmp.c_str(), X_OK) == 0)
- return true;
- }
- }
- return false;
- }
- void Gnuplot::reset_plot(void)
- {
- if (this->to_delete.size() > 0)
- {
- for (vector<string>::size_type i = 0; i < this->to_delete.size(); i++)
- remove(this->to_delete[i].c_str());
- to_delete.clear();
- }
- this->nplots = 0;
- return;
- }
- void Gnuplot::set_style(const std::string &stylestr)
- {
- if (stylestr != "lines" && stylestr != "points" && stylestr
- != "linespoints" && stylestr != "impulses" && stylestr != "dots"
- && stylestr != "steps" && stylestr != "errorbars" && stylestr
- != "boxes" && stylestr != "boxerrorbars")
- this->pstyle = string("points");
- else
- this->pstyle = stylestr;
- }
- void Gnuplot::cmd(const char *cmdstr, ...)
- {
- va_list ap;
- char local_cmd[GP_CMD_SIZE];
- va_start(ap, cmdstr);
- vsprintf(local_cmd, cmdstr, ap);
- va_end(ap);
- strcat(local_cmd, "\n");
- fputs(local_cmd, this->gnucmd);
- fflush(this->gnucmd);
- return;
- }
- void Gnuplot::setFileOutput(const string &terminal, const string &filename)
- {
- ostringstream cmdstr;
- cmdstr << "set terminal " << terminal;
- this->cmd(cmdstr.str().c_str());
- cmdstr.str("");
- cmdstr << "set output \"" << filename << "\"";
- this->cmd(cmdstr.str().c_str());
- }
- void Gnuplot::set_ylabel(const std::string &label)
- {
- std::ostringstream cmdstr;
- cmdstr << "set xlabel \"" << label << "\"";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- void Gnuplot::set_xlabel(const std::string &label)
- {
- std::ostringstream cmdstr;
- cmdstr << "set xlabel \"" << label << "\"";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- void Gnuplot::set_zlabel(const std::string &label)
- {
- std::ostringstream cmdstr;
- cmdstr << "set zlabel \"" << label << "\"";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- // set the xrange
- void Gnuplot::set_xrange(const int iFrom, const int iTo)
- {
- std::ostringstream cmdstr;
- cmdstr << "set xrange[" << iFrom << ":" << iTo << "]";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- // set the yrange
- void Gnuplot::set_yrange(const int iFrom, const int iTo)
- {
- std::ostringstream cmdstr;
- cmdstr << "set yrange[" << iFrom << ":" << iTo << "]";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- // set the zrange
- void Gnuplot::set_zrange(const int iFrom, const int iTo)
- {
- std::ostringstream cmdstr;
- cmdstr << "set zrange[" << iFrom << ":" << iTo << "]";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- // set the palette range
- void Gnuplot::set_cbrange(const int iFrom, const int iTo)
- {
- std::ostringstream cmdstr;
- cmdstr << "set cbrange[" << iFrom << ":" << iTo << "]";
- this->cmd(cmdstr.str().c_str());
- return;
- }
- //
- // Plots a linear equation (where you supply the
- // slope and intercept)
- //
- void Gnuplot::plot_slope(double a, double b, const std::string &title)
- {
- std::ostringstream stitle;
- std::ostringstream cmdstr;
- if (title == "")
- stitle << "no title";
- else
- stitle << title;
- if (this->nplots > 0)
- cmdstr << "replot " << a << " * x + " << b << " title \""
- << stitle.str() << "\" with " << pstyle;
- else
- cmdstr << "plot " << a << " * x + " << b << " title \"" << stitle.str()
- << "\" with " << pstyle;
- this->cmd(cmdstr.str().c_str());
- this->nplots++;
- return;
- }
- //
- // Plot an equation which is supplied as a string
- //
- void Gnuplot::plot_equation(const std::string &equation,
- const std::string &title)
- {
- std::string titlestr, plotstr;
- std::ostringstream cmdstr;
- if (title == "")
- titlestr = "no title";
- else
- titlestr = title;
- if (this->nplots > 0)
- plotstr = "replot";
- else
- plotstr = "plot";
- cmdstr << plotstr << " " << equation << " " << "title \"" << titlestr
- << "\" with " << this->pstyle;
- this->cmd(cmdstr.str().c_str());
- this->nplots++;
- return;
- }
- void Gnuplot::plot_x(vector<double> d, const std::string &title)
- {
- ofstream tmp;
- std::ostringstream cmdstr;
- char name[] = "/tmp/gnuplotiXXXXXX";
- if (this->to_delete.size() == GP_MAX_TMP_FILES - 1)
- {
- cerr << "Maximum number of temporary files reached ("
- << GP_MAX_TMP_FILES << "): cannot open more files" << endl;
- return;
- }
- //
- //open temporary files for output
- if (mkstemp(name) == -1)
- {
- cerr << "Cannot create temporary file: exiting plot" << endl;
- return;
- }
- tmp.open(name);
- if (tmp.bad())
- {
- cerr << "Cannot create temorary file: exiting plot" << endl;
- return;
- }
- //
- // Save the temporary filename
- //
- this->to_delete.push_back(name);
- //
- // write the data to file
- //
- for (vector<double>::size_type i = 0; i < d.size(); i++)
- tmp << d[i] << endl;
- tmp.flush();
- tmp.close();
- //
- // command to be sent to gnuplot
- //
- if (this->nplots > 0)
- cmdstr << "replot ";
- else
- cmdstr << "plot ";
- if (title == "")
- cmdstr << "\"" << name << "\" with " << this->pstyle;
- else
- cmdstr << "\"" << name << "\" title \"" << title << "\" with "
- << this->pstyle;
- //
- // Do the actual plot
- //
- this->cmd(cmdstr.str().c_str());
- this->nplots++;
- return;
- }
- void Gnuplot::plot_xy(map<double, double> xy, const std::string &title)
- {
- vector<double> x;
- vector<double> y;
- for (map<double, double>::const_iterator i = xy.begin(); i != xy.end(); i++)
- {
- x.push_back(i->first);
- y.push_back(i->second);
- }
- plot_xy(x, y, title);
- }
- void Gnuplot::plot_xy(vector<double> x, vector<double> y,
- const std::string &title)
- {
- ofstream tmp;
- std::ostringstream cmdstr;
- char name[] = "/tmp/gnuplotiXXXXXX";
- // should raise an exception
- if (x.size() != y.size())
- return;
- if ((this->to_delete).size() == GP_MAX_TMP_FILES - 1)
- {
- cerr << "Maximum number of temporary files reached ("
- << GP_MAX_TMP_FILES << "): cannot open more files" << endl;
- return;
- }
- //
- //open temporary files for output
- //
- if (mkstemp(name) == -1)
- {
- cerr << "Cannot create temporary file: exiting plot" << endl;
- return;
- }
- tmp.open(name);
- if (tmp.bad())
- {
- cerr << "Cannot create temorary file: exiting plot" << endl;
- return;
- }
- //
- // Save the temporary filename
- //
- this->to_delete.push_back(name);
- //
- // write the data to file
- //
- for (vector<double>::size_type i = 0; i < x.size(); i++)
- tmp << x[i] << " " << y[i] << endl;
- tmp.flush();
- tmp.close();
- //
- // command to be sent to gnuplot
- //
- if (this->nplots > 0)
- cmdstr << "replot ";
- else
- cmdstr << "plot ";
- if (title == "")
- cmdstr << "\"" << name << "\" with " << this->pstyle;
- else
- cmdstr << "\"" << name << "\" title \"" << title << "\" with "
- << this->pstyle;
- //
- // Do the actual plot
- //
- this->cmd(cmdstr.str().c_str());
- this->nplots++;
- return;
- }
- void Gnuplot::plot_xyz(vector<double> x, vector<double> y, vector<double> z,
- const std::string &title)
- {
- ofstream tmp;
- std::ostringstream cmdstr;
- char name[] = "/tmp/gnuplotiXXXXXX";
- // should raise an exception
- if (x.size() != y.size() || x.size() != z.size())
- {
- return;
- }
- if ((this->to_delete).size() == GP_MAX_TMP_FILES - 1)
- {
- cerr << "Maximum number of temporary files reached ("
- << GP_MAX_TMP_FILES << "): cannot open more files" << endl;
- return;
- }
- //
- //open temporary files for output
- //
- if (mkstemp(name) == -1)
- {
- cerr << "Cannot create temporary file: exiting plot" << endl;
- return;
- }
- tmp.open(name);
- if (tmp.bad())
- {
- cerr << "Cannot create temorary file: exiting plot" << endl;
- return;
- }
- //
- // Save the temporary filename
- //
- this->to_delete.push_back(name);
- //
- // write the data to file
- //
- for (unsigned int i = 0; i < x.size(); i++)
- {
- tmp << x[i] << " " << y[i] << " " << z[i] << endl;
- }
- tmp.flush();
- tmp.close();
- //
- // command to be sent to gnuplot
- //
- if (this->nplots > 0)
- cmdstr << "replot ";
- else
- cmdstr << "splot ";
- if (title == "")
- cmdstr << "\"" << name << "\" with " << this->pstyle;
- else
- cmdstr << "\"" << name << "\" title \"" << title << "\" with "
- << this->pstyle;
- //
- // Do the actual plot
- //
- this->cmd(cmdstr.str().c_str());
- this->nplots++;
- return;
- }
- /**
- * note that this function is not valid for versions of GNUPlot below 4.2
- *
- **/
- void Gnuplot::plot_image(unsigned char * ucPicBuf, int iWidth, int iHeight,
- const std::string &title)
- {
- ofstream tmp;
- std::ostringstream cmdstr;
- char name[] = "/tmp/gnuplotiXXXXXX";
- if ((this->to_delete).size() == GP_MAX_TMP_FILES - 1)
- {
- cerr << "Maximum number of temporary files reached ("
- << GP_MAX_TMP_FILES << "): cannot open more files" << endl;
- return;
- }
- //
- //open temporary files for output
- //
- if (mkstemp(name) == -1)
- {
- cerr << "Cannot create temporary file: exiting plot" << endl;
- return;
- }
- tmp.open(name);
- if (tmp.bad())
- {
- cerr << "Cannot create temorary file: exiting plot" << endl;
- return;
- }
- //
- // Save the temporary filename
- //
- this->to_delete.push_back(name);
- //
- // write the data to file
- //
- int iIndex = 0;
- for (int iRow = 0; iRow < iHeight; iRow++)
- {
- for (int iColumn = 0; iColumn < iWidth; iColumn++)
- {
- tmp << iColumn << " " << iRow << " "
- << static_cast<float> (ucPicBuf[iIndex++]) << endl;
- ;
- }
- }
- tmp.flush();
- tmp.close();
- //
- // command to be sent to gnuplot
- //
- if (this->nplots > 0)
- cmdstr << "replot ";
- else
- cmdstr << "plot ";
- if (title == "")
- cmdstr << "\"" << name << "\" with " << this->pstyle;
- else
- cmdstr << "\"" << name << "\" title \"" << title << "\" with image ";// << this->pstyle;
- //
- // Do the actual plot
- //
- this->cmd(cmdstr.str().c_str());
- this->nplots++;
- return;
- }
|