You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

350 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi.
  4. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
  5. Copyright 2007 by Julian Storer.
  6. ------------------------------------------------------------------------------
  7. JUCE and JUCETICE can be redistributed and/or modified under the terms of
  8. the GNU General Public License, as published by the Free Software Foundation;
  9. either version 2 of the License, or (at your option) any later version.
  10. JUCE and JUCETICE are distributed in the hope that they will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
  16. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  17. Boston, MA 02111-1307 USA
  18. ==============================================================================
  19. Created by Richel Bilderbeek on Fri Jun 10 2005.
  20. ==============================================================================
  21. */
  22. #if JUCE_LINUX
  23. #include <iostream>
  24. #include <string>
  25. #include <fstream>
  26. #include <sstream>
  27. #include <cstdio>
  28. BEGIN_JUCE_NAMESPACE
  29. //==============================================================================
  30. //#define EXTENSIVE_LOG
  31. int Gnuplot::mTempFileNumber = 0;
  32. //==============================================================================
  33. Gnuplot::Gnuplot() :
  34. mGnuPipe (0),
  35. mTerminal ("wxt"),
  36. mStyle ("lines"),
  37. mCurrentWindowNumber(0)
  38. {
  39. File file (readFileName());
  40. if (! file.exists ())
  41. {
  42. printf ("Gnuplot executable not found.\n");
  43. return;
  44. }
  45. printf ("Gnuplot executable found at '%s'.\n", (const char*) file.getFullPathName().toUTF8());
  46. printf ("Opening pipe to Gnuplot\n");
  47. String fileName = file.getFullPathName ();
  48. mGnuPipe = ::popen ((const char*) (fileName + " -persist").toUTF8(), "w"); //Changed 'rw' to 'w'
  49. if (mGnuPipe==0)
  50. {
  51. printf ("Couldn't open connection to gnuplot\n");
  52. return;
  53. }
  54. setLineStyles ();
  55. addWindow ();
  56. changeWindow (0);
  57. }
  58. Gnuplot::~Gnuplot()
  59. {
  60. for (int i = 0; i != mWindowData.size(); ++i)
  61. {
  62. mCurrentWindowNumber = i;
  63. emptyPlot();
  64. }
  65. if (::pclose ((FILE*) mGnuPipe) == -1)
  66. {
  67. jassert(!"Problem closing communication to Gnuplot");
  68. }
  69. }
  70. //==============================================================================
  71. const String Gnuplot::readFileName() const
  72. {
  73. String returnFileName;
  74. returnFileName ="/usr/bin/gnuplot";
  75. return returnFileName;
  76. }
  77. //==============================================================================
  78. void Gnuplot::emptyPlot()
  79. {
  80. const int nPlots = mWindowData[mCurrentWindowNumber].size();
  81. for (int i = 0; i != nPlots; ++i)
  82. {
  83. DBG ("Removing file: " + mWindowData[mCurrentWindowNumber][i]);
  84. File file (mWindowData[mCurrentWindowNumber][i]);
  85. file.deleteFile ();
  86. }
  87. }
  88. //==============================================================================
  89. void Gnuplot::setTerminal (const GnuplotTerminal& terminal)
  90. {
  91. switch(terminal)
  92. {
  93. case terminalPng : mTerminal = "png"; break;
  94. case terminalWxt : mTerminal = "wxt"; break;
  95. case terminalX11 : mTerminal = "x11" ; break;
  96. default: jassert (!"Unknown GnuplotTerminal");
  97. }
  98. }
  99. void Gnuplot::setStyle (const GnuplotStyle& style)
  100. {
  101. switch(style)
  102. {
  103. case styleLines : mStyle = "lines"; break;
  104. case stylePoints : mStyle = "points"; break;
  105. case styleLinespoints : mStyle = "linespoints"; break;
  106. case styleImpulses : mStyle = "impulses"; break;
  107. case styleDots : mStyle = "dots"; break;
  108. case styleSteps : mStyle = "steps"; break;
  109. case styleErrorbars : mStyle = "errorbars"; break;
  110. case styleBoxes : mStyle = "boxes"; break;
  111. case styleBoxerrorbars : mStyle = "boxerrorbars"; break;
  112. default: jassert (!"Unknown GnuplotStyle");
  113. }
  114. }
  115. void Gnuplot::setYlabel (const String& label)
  116. {
  117. const String command = "set ylabel \""+label+"\"";
  118. execute (command);
  119. }
  120. void Gnuplot::setXlabel (const String& label)
  121. {
  122. const String command = "set xlabel \""+label+"\"";
  123. execute (command);
  124. }
  125. void Gnuplot::setOutput (const String& output)
  126. {
  127. const String command = "set output \""+output+"\"";
  128. execute (command);
  129. }
  130. void Gnuplot::setMultiplot (const bool isMultiple)
  131. {
  132. const String command = (isMultiple ? "set multiplot" : "unset multiplot");
  133. execute (command);
  134. }
  135. //==============================================================================
  136. void Gnuplot::changeWindow(const int windowNumber)
  137. {
  138. if (windowNumber == mCurrentWindowNumber) return;
  139. if (windowNumber >= static_cast<int>(mWindowData.size()))
  140. {
  141. addWindow();
  142. mCurrentWindowNumber = mWindowData.size()-1;
  143. }
  144. else
  145. {
  146. mCurrentWindowNumber = windowNumber;
  147. }
  148. const String myCommand = "set terminal " + mTerminal + " " + String (mCurrentWindowNumber + 1);
  149. execute (myCommand);
  150. }
  151. void Gnuplot::addWindow (const int nWindows)
  152. {
  153. for (int i = 0; i != nWindows; ++i)
  154. {
  155. StringArray temp;
  156. mWindowData.add (temp);
  157. }
  158. }
  159. //==============================================================================
  160. void Gnuplot::plot (const String &equation, const String &title)
  161. {
  162. String myCommand;
  163. if (mWindowData[mCurrentWindowNumber].size() > 0)
  164. myCommand = "replot " + equation + " title \"" + title + "\" with " + mStyle;
  165. else
  166. myCommand = "plot " + equation + " title \"" + title + "\" with " + mStyle;
  167. execute (myCommand);
  168. }
  169. void Gnuplot::plot (const Array<double>& x, const String &title)
  170. {
  171. const String tempFileName = createTempFileName();
  172. createTempFile (tempFileName, x);
  173. plotTempFile2D (tempFileName, title);
  174. }
  175. void Gnuplot::plot (const Array<double>& x, const Array<double>& y, const String &title)
  176. {
  177. const String tempFileName = createTempFileName();
  178. createTempFile (tempFileName, x, y);
  179. plotTempFile2D (tempFileName, title);
  180. }
  181. void Gnuplot::plot (const Array<double>& x, const Array<double>& y, const Array<double>& z, const String &title)
  182. {
  183. const String tempFileName = createTempFileName();
  184. createTempFile (tempFileName, x, y, z);
  185. plotTempFile3D (tempFileName, title);
  186. }
  187. void Gnuplot::plotTempFile2D (const String& tempFileName, const String& title)
  188. {
  189. String myCommand;
  190. const int nSeries = mWindowData[mCurrentWindowNumber].size();
  191. /*
  192. //Linestyles are nice, but don't work on my terminal...
  193. ///if (nSeries>12) printf ("MAKE MORE LINESTYLES!!!\n");
  194. //if ( nSeries == 0)
  195. // myCommand = "plot \"" + tempFileName + "\" ls "+String(nSerie)+" title \"" + title + "\" with " + mStyle;
  196. //else
  197. // myCommand = "replot \"" + tempFileName + "\" ls "+String(nSerie)+" title \"" + title + "\" with " + mStyle;
  198. */
  199. if ( nSeries == 0)
  200. myCommand = "plot \"" + tempFileName + "\" title \"" + title + "\" with " + mStyle;
  201. else
  202. myCommand = "replot \"" + tempFileName + "\" title \"" + title + "\" with " + mStyle;
  203. execute (myCommand);
  204. Thread::sleep (1000);
  205. mWindowData[mCurrentWindowNumber].add (tempFileName);
  206. }
  207. void Gnuplot::plotTempFile3D (const String& tempFileName, const String& title)
  208. {
  209. //Does not work on my computer. Should be something like this...
  210. execute ("set pm3d");
  211. String myCommand;
  212. if (mWindowData[mCurrentWindowNumber].size() == 0)
  213. myCommand = "splot \"" + tempFileName + "\" title \"" + title + "\" with pm3d palette";
  214. else
  215. myCommand = "replot \"" + tempFileName + "\" title \"" + title + "\" with pm3d palette";
  216. execute (myCommand);
  217. Thread::sleep (1000);
  218. mWindowData[mCurrentWindowNumber].add(tempFileName);
  219. }
  220. //==============================================================================
  221. const String Gnuplot::createTempFileName()
  222. {
  223. ++mTempFileNumber;
  224. const File tempFile = File::createTempFile ("GnuplotTemp" + String (mTempFileNumber));
  225. DBG ("Created temp file '" + tempFile.getFullPathName () + "'");
  226. return tempFile.getFullPathName ();
  227. }
  228. void Gnuplot::createTempFile (const String& tempFileName,
  229. const Array<double>& x)
  230. {
  231. File file (tempFileName);
  232. FileOutputStream* out = file.createOutputStream ();
  233. const int size = x.size();
  234. for (int i = 0; i != size; i++)
  235. *out << x[i] << "\n";
  236. delete out;
  237. }
  238. void Gnuplot::createTempFile (const String& tempFileName,
  239. const Array<double>& x,
  240. const Array<double>& y)
  241. {
  242. jassert (x.size() == y.size());
  243. File file (tempFileName);
  244. FileOutputStream* out = file.createOutputStream ();
  245. const int size = x.size();
  246. for (int i = 0; i != size; i++)
  247. *out << x[i] << " " << y[i] << "\n";
  248. delete out;
  249. }
  250. void Gnuplot::createTempFile (const String& tempFileName,
  251. const Array<double>& x,
  252. const Array<double>& y,
  253. const Array<double>& z)
  254. {
  255. jassert (x.size() == y.size());
  256. jassert (y.size() == z.size());
  257. File file (tempFileName);
  258. FileOutputStream* out = file.createOutputStream ();
  259. const int size = x.size();
  260. for (int i = 0; i != size; i++)
  261. *out << x[i] << " " << y[i] << " " << z[i] << "\n";
  262. delete out;
  263. }
  264. //==============================================================================
  265. void Gnuplot::setLineStyles()
  266. {
  267. //Does not work on all terminals. Like mine... :-(
  268. //Execute("set style line 1 lt pal frac 0.0 lw 2");
  269. //Execute("set style line 2 lt pal frac 0.0 lw 4");
  270. //Execute("set style line 3 lt pal frac 0.2 lw 2");
  271. //Execute("set style line 4 lt pal frac 0.2 lw 4");
  272. //Execute("set style line 5 lt pal frac 0.4 lw 2");
  273. //Execute("set style line 6 lt pal frac 0.4 lw 4");
  274. //Execute("set style line 7 lt pal frac 0.6 lw 2");
  275. //Execute("set style line 8 lt pal frac 0.6 lw 4");
  276. //Execute("set style line 9 lt pal frac 0.8 lw 2");
  277. //Execute("set style line 10 lt pal frac 0.8 lw 4");
  278. //Execute("set style line 11 lt pal frac 1.0 lw 2");
  279. //Execute("set style line 12 lt pal frac 1.0 lw 4");
  280. }
  281. //==============================================================================
  282. void Gnuplot::execute(const String& cmdstr) const
  283. {
  284. DBG ("Command sent to Gnuplot: " + cmdstr);
  285. ::fputs ((const char*) (cmdstr+"\n").toUTF8(), (FILE*) mGnuPipe);
  286. ::fflush ((FILE*) mGnuPipe);
  287. Thread::sleep (1000);
  288. }
  289. END_JUCE_NAMESPACE
  290. #endif