From 674263dde7a2c65be1b344ff6ffe1d590f46ebf9 Mon Sep 17 00:00:00 2001 From: Antonin Portelli Date: Thu, 18 Sep 2014 17:13:26 +0100 Subject: [PATCH] Plot: function to save plots --- lib/Plot.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++------ lib/Plot.hpp | 8 ++-- 2 files changed, 101 insertions(+), 14 deletions(-) diff --git a/lib/Plot.cpp b/lib/Plot.cpp index e5f8889..22d156d 100644 --- a/lib/Plot.cpp +++ b/lib/Plot.cpp @@ -195,9 +195,17 @@ void LogScale::operator()(PlotOptions &option) const option.scaleMode[static_cast(axis_)] |= Plot::Scale::log; } -// PlotRange constructor //////////////////////////////////////////////////////// +// PlotRange constructors ////////////////////////////////////////////////////// +PlotRange::PlotRange(const Axis axis) +: axis_(axis) +, reset_(true) +, min_(0.) +, max_(0.) +{} + PlotRange::PlotRange(const Axis axis, const double min, const double max) : axis_(axis) +, reset_(false) , min_(min) , max_(max) {} @@ -207,9 +215,16 @@ void PlotRange::operator()(PlotOptions &option) const { int a = static_cast(axis_); - option.scaleMode[a] |= Plot::Scale::manual; - option.scale[a].min = min_; - option.scale[a].max = max_; + if (!reset_) + { + option.scaleMode[a] |= Plot::Scale::manual; + option.scale[a].min = min_; + option.scale[a].max = max_; + } + else + { + option.scaleMode[a] = Plot::Scale::reset; + } } // Terminal constructor //////////////////////////////////////////////////////// @@ -252,15 +267,15 @@ Plot::~Plot(void) // clean temporary files /////////////////////////////////////////////////////// void Plot::cleanTmpFiles(void) { - while (!tmpFileName_.empty()) + for (string &fileName: tmpFileName_) { - if (remove(tmpFileName_.top().c_str())) + if (remove(fileName.c_str())) { LATAN_ERROR(System, "impossible to remove temporary file '" + - tmpFileName_.top() + "'"); + fileName + "'"); } - tmpFileName_.pop(); } + tmpFileName_.clear(); } // default options ///////////////////////////////////////////////////////////// @@ -295,7 +310,8 @@ Plot & Plot::operator<<(PlotObject &&command) while (command.gotTmpFile()) { - tmpFileName_.push(command.popTmpFile()); + tmpFileName_.push_back(command.popTmpFile()); + commandStr += "'" + tmpFileName_.back() + "' "; } commandStr = command.getCommand(); if (!options_.lineColor.empty()) @@ -390,7 +406,7 @@ void Plot::getProgramPath(void) // plot parsing and output ///////////////////////////////////////////////////// void Plot::display(void) { - std::string command; + string command; FILE *gnuplotPipe; if (!getenv("DISPLAY")) @@ -414,6 +430,75 @@ void Plot::display(void) } } +void Plot::save(string dirName) +{ + vector commandBack; + string path, terminalBack, outputBack, gpCommand, scriptName; + mode_t mode755; + ofstream script; + + mode755 = S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; + + // backup I/O parameters + terminalBack = options_.terminal; + outputBack = options_.output; + commandBack = plotCommand_; + + // generate directory + if (access(dirName.c_str(), R_OK|W_OK|X_OK)) + { + if (mkdir(dirName.c_str(), mode755)) + { + LATAN_ERROR(Io, "impossible to create directory '" + dirName + "'"); + } + } + + // save PDF + options_.terminal = "pdf"; + options_.output = dirName + "/plot.pdf"; + display(); + options_.terminal = terminalBack; + options_.output = outputBack; + + // save script and datafiles + for (unsigned int i = 0; i < tmpFileName_.size(); ++i) + { + ofstream dataFile; + ifstream tmpFile; + string dataFileName = "points_" + strFrom(i) + ".dat"; + + dataFile.open(dirName + "/" + dataFileName); + tmpFile.open(tmpFileName_[i]); + dataFile << tmpFile.rdbuf(); + dataFile.close(); + tmpFile.close(); + for (string &command: plotCommand_) + { + auto pos = command.find(tmpFileName_[i]); + + while (pos != string::npos) + { + command.replace(pos, tmpFileName_[i].size(), dataFileName); + pos = command.find(tmpFileName_[i], pos + 1); + } + } + } + scriptName = dirName + "/source.plt"; + script.open(scriptName); + getProgramPath(); + gpCommand = gnuplotPath_ + "/" + gnuplotBin_ + " " + gnuplotArgs_; + script << "#!/usr/bin/env " << gpCommand << "\n" << endl; + script << "# script generated by " << Env::fullName << "\n" << endl; + script << *this; + script.close(); + if (chmod(scriptName.c_str(), mode755)) + { + LATAN_ERROR(Io, "impossible to set file '" + scriptName + + "' in mode 755"); + } + plotCommand_ = commandBack; +} + ostream & Latan::operator<<(ostream &out, const Plot &plot) { std::string begin, end; @@ -425,7 +510,7 @@ ostream & Latan::operator<<(ostream &out, const Plot &plot) } if (!plot.options_.output.empty()) { - out << "set output '" << plot.options_.terminal << "'" << endl; + out << "set output '" << plot.options_.output << "'" << endl; } if (!plot.options_.caption.empty()) { diff --git a/lib/Plot.hpp b/lib/Plot.hpp index 9e4154d..8a9710c 100644 --- a/lib/Plot.hpp +++ b/lib/Plot.hpp @@ -24,7 +24,6 @@ #include #include #include -#include #include // gnuplot default parameters @@ -176,7 +175,8 @@ private: class PlotRange: public PlotModifier { public: - // constructor + // constructors + PlotRange(const Axis axis); PlotRange(const Axis axis, const double min, const double max); // destructor virtual ~PlotRange(void) = default; @@ -184,6 +184,7 @@ public: virtual void operator()(PlotOptions &option) const; private: const Axis axis_; + const bool reset_; const double min_, max_; }; @@ -238,6 +239,7 @@ public: Plot & operator<<(PlotModifier &&modifier); // plot parsing and output void display(void); + void save(std::string dirName); friend std::ostream & operator<<(std::ostream &out, const Plot &plot); // plot reset void reset(void); @@ -256,7 +258,7 @@ private: // string buffer for commands std::ostringstream commandBuffer_; // stack of created temporary files - std::stack tmpFileName_; + std::vector tmpFileName_; // plot content PlotOptions options_; std::vector headCommand_;