00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2007 INRIA, 2008 Timo Bingmann 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation; 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 * Original Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> 00019 * Enhancements: Timo Bingmann <timo.bingmann@student.kit.edu> 00020 */ 00021 #ifndef GNUPLOT_H 00022 #define GNUPLOT_H 00023 00024 #include <string> 00025 #include <vector> 00026 #include <utility> 00027 00028 namespace ns3 { 00029 00030 /** 00031 * \brief Abstract class to store a plot line to be used by ns3::Gnuplot. 00032 * 00033 * This class contains a reference counted data object in m_data. The data 00034 * object contains different structs derived from struct Data by subclasses. 00035 */ 00036 class GnuplotDataset 00037 { 00038 public: 00039 00040 /** 00041 * Reference-counting copy constructor. 00042 */ 00043 GnuplotDataset (const GnuplotDataset& original); 00044 00045 /** 00046 * Reference-counting destructor. 00047 */ 00048 ~GnuplotDataset(); 00049 00050 /** 00051 * Reference-counting assignment operator. 00052 */ 00053 GnuplotDataset& operator= (const GnuplotDataset& original); 00054 00055 /** 00056 * \brief Change line title. 00057 * \param title the new title string to use for this dataset. 00058 */ 00059 void SetTitle (const std::string& title); 00060 00061 /** 00062 * \brief Change extra formatting style parameters for newly created objects. 00063 * \param extra extra formatting 00064 */ 00065 static void SetDefaultExtra (const std::string& extra); 00066 00067 /** 00068 * \brief Add extra formatting parameters to this dataset. 00069 * \param extra extra formatting 00070 */ 00071 void SetExtra (const std::string& extra); 00072 00073 protected: 00074 00075 /// Friend because it accesses m_data and it's virtual functions directly in 00076 /// GenerateOutput(). 00077 friend class Gnuplot; 00078 00079 /** 00080 * \brief Extra gnuplot parameters set on every newly created dataset. 00081 */ 00082 static std::string m_defaultExtra; 00083 00084 /** 00085 * \brief Derived classes subclass this struct and add their own data fields. 00086 */ 00087 struct Data; 00088 00089 /** 00090 * Called by constructors of derived classes. 00091 * \param data the reference counted data object representing this dataset. 00092 */ 00093 GnuplotDataset (struct Data* data); 00094 00095 /** 00096 * Reference counted data object. 00097 */ 00098 struct Data* m_data; 00099 }; 00100 00101 /** 00102 * \brief Class to represent a 2D points plot. Set the line or points style 00103 * using SetStyle() and set points using Add(). 00104 */ 00105 class Gnuplot2dDataset : public GnuplotDataset 00106 { 00107 public: 00108 /** 00109 * The plotting style to use for this dataset. 00110 */ 00111 enum Style { 00112 LINES, 00113 POINTS, 00114 LINES_POINTS, 00115 DOTS, 00116 IMPULSES, 00117 STEPS, 00118 FSTEPS, 00119 HISTEPS, 00120 }; 00121 00122 /** 00123 * Whether errorbars should be used for this dataset. 00124 */ 00125 enum ErrorBars { 00126 NONE, 00127 X, 00128 Y, 00129 XY 00130 }; 00131 00132 /** 00133 * \param title the title to be associated to this dataset. 00134 * 00135 * Create an empty dataset. Usually, the dataset's title is 00136 * displayed in the legend box. 00137 */ 00138 Gnuplot2dDataset (const std::string& title = "Untitled"); 00139 00140 /** 00141 * Change default style for all newly created objects. 00142 * \param style the style of plotting to use for newly created datasets. 00143 */ 00144 static void SetDefaultStyle (enum Style style); 00145 00146 /** 00147 * \param style the style of plotting to use for this dataset. 00148 */ 00149 void SetStyle (enum Style style); 00150 00151 /** 00152 * Change default errorbars style for all newly created objects. 00153 * \param errorBars the style of errorbars to use for newly created datasets. 00154 */ 00155 static void SetDefaultErrorBars (enum ErrorBars errorBars); 00156 00157 /** 00158 * \param errorBars the style of errorbars to display. 00159 * 00160 * If you use any style other than none, you need 00161 * to make sure you store the delta information in 00162 * this dataset with the right GnuplotDataset::Add 00163 * method. 00164 */ 00165 void SetErrorBars (enum ErrorBars errorBars); 00166 00167 /** 00168 * \param x x coord to new data point 00169 * \param y y coord to new data point 00170 * 00171 * Use this method with error bar style NONE. 00172 */ 00173 void Add (double x, double y); 00174 00175 /** 00176 * \param x x coord to new data point 00177 * \param y y coord to new data point 00178 * \param errorDelta data point error range. 00179 * 00180 * Use this method with error bar style X or Y. 00181 */ 00182 void Add (double x, double y, double errorDelta); 00183 00184 /** 00185 * \param x x coord to new data point 00186 * \param y y coord to new data point 00187 * \param minY minimum error data point 00188 * \param maxY maximum error data point 00189 * 00190 * Use this method with error bar style X or Y. 00191 */ 00192 void Add (double x, double y, double minY, double maxY); 00193 00194 /** 00195 * Add an empty line in the data output sequence. Empty lines in the plot 00196 * data break continuous lines and do other things in the output. 00197 */ 00198 void AddEmptyLine(); 00199 00200 private: 00201 00202 struct Point { 00203 bool empty; 00204 double x; 00205 double y; 00206 double dx; 00207 double dy; 00208 }; 00209 00210 typedef std::vector<struct Point> PointSet; 00211 00212 static enum Style m_defaultStyle; 00213 static enum ErrorBars m_defaultErrorBars; 00214 00215 /// Forward declaration of the internal data class. 00216 struct Data2d; 00217 }; 00218 00219 /** 00220 * \brief Class to represent a 2D function expression plot. 00221 * 00222 * Since the function expression is not escaped, styles and extras could just 00223 * as well be included in the expression string. 00224 */ 00225 class Gnuplot2dFunction : public GnuplotDataset 00226 { 00227 public: 00228 /** 00229 * \param title the title to be associated to this dataset. 00230 * \param function function to plot 00231 * 00232 * Create an function dataset. Usually, the dataset's title is displayed in 00233 * the legend box. 00234 */ 00235 Gnuplot2dFunction (const std::string& title = "Untitled", const std::string& function = ""); 00236 00237 /** 00238 * \param function new function string to set 00239 */ 00240 void SetFunction (const std::string& function); 00241 00242 private: 00243 00244 /// Forward declaration of the internal data class. 00245 struct Function2d; 00246 }; 00247 00248 /** 00249 * \brief Class to represent a 3D points plot. Set the line or points style 00250 * using SetStyle() and set points using Add(). 00251 */ 00252 class Gnuplot3dDataset : public GnuplotDataset 00253 { 00254 public: 00255 /** 00256 * \param title the title to be associated to this dataset. 00257 * 00258 * Create an empty dataset. Usually, the dataset's title is 00259 * displayed in the legend box. 00260 */ 00261 Gnuplot3dDataset (const std::string& title = "Untitled"); 00262 00263 /** 00264 * Change default style for all newly created objects. 00265 * \param style the style of plotting to use for newly created datasets. 00266 */ 00267 static void SetDefaultStyle (const std::string& style); 00268 00269 /** 00270 * \param style the style of plotting to use for this dataset. 00271 */ 00272 void SetStyle (const std::string& style); 00273 00274 /** 00275 * \param x x coord to new data point 00276 * \param y y coord to new data point 00277 * \param z z coord to new data point 00278 * 00279 * Use this method to add a new 3D point 00280 */ 00281 void Add (double x, double y, double z); 00282 00283 /** 00284 * Add an empty line in the data output sequence. Empty lines in the plot 00285 * data break continuous lines and do other things in the output. 00286 */ 00287 void AddEmptyLine(); 00288 00289 private: 00290 00291 struct Point { 00292 bool empty; 00293 double x, y, z; 00294 }; 00295 00296 typedef std::vector<struct Point> PointSet; 00297 00298 static std::string m_defaultStyle; 00299 00300 /// Forward declaration of the internal data class. 00301 struct Data3d; 00302 }; 00303 00304 /** 00305 * \brief Class to represent a 3D function expression plot. 00306 * 00307 * Since the function expression is not escaped, styles and extras could just as 00308 * well be included in the expression string. The only difference to 00309 * Gnuplot2dFunction is the splot command string. 00310 */ 00311 class Gnuplot3dFunction : public GnuplotDataset 00312 { 00313 public: 00314 /** 00315 * \param title the title to be associated to this dataset. 00316 * \param function function to plot 00317 * 00318 * Create an function dataset. Usually, the dataset's title is displayed in 00319 * the legend box. 00320 */ 00321 Gnuplot3dFunction (const std::string& title = "Untitled", const std::string& function = ""); 00322 00323 /** 00324 * \param function new function string to set 00325 */ 00326 void SetFunction (const std::string& function); 00327 00328 private: 00329 00330 /// Forward declaration of the internal data class. 00331 struct Function3d; 00332 }; 00333 00334 /** 00335 * \brief a simple class to generate gnuplot-ready plotting commands 00336 * from a set of datasets. 00337 * 00338 * This class really represents a single graph on which multiple datasets 00339 * can be plotted. 00340 */ 00341 class Gnuplot 00342 { 00343 public: 00344 /** 00345 * \param outputFilename the name of the file where the rendering of the 00346 * graph will be generated if you feed the command stream output by 00347 * Gnuplot::GenerateOutput to the gnuplot program. 00348 * \param title title line of the plot page 00349 */ 00350 Gnuplot (const std::string& outputFilename="", const std::string& title = ""); 00351 00352 /** 00353 * Crude attempt to auto-detect the correct terminal setting by inspecting 00354 * the filename's extension. 00355 * \param filename output file name 00356 */ 00357 static std::string DetectTerminal(const std::string& filename); 00358 00359 /** 00360 * \param terminal terminal setting string for output. The default terminal 00361 * string is "png" 00362 */ 00363 void SetTerminal (const std::string& terminal); 00364 00365 /** 00366 * \param title set new plot title string to use for this plot. 00367 */ 00368 void SetTitle (const std::string& title); 00369 00370 /** 00371 * \param xLegend the legend for the x horizontal axis 00372 * \param yLegend the legend for the y vertical axis 00373 */ 00374 void SetLegend (const std::string& xLegend, const std::string& yLegend); 00375 00376 /** 00377 * \param extra set extra gnuplot directive for output. 00378 */ 00379 void SetExtra (const std::string& extra); 00380 00381 /** 00382 * \param extra append extra gnuplot directive for output. 00383 */ 00384 void AppendExtra (const std::string& extra); 00385 00386 /** 00387 * \param dataset add a dataset to the graph to be plotted. 00388 */ 00389 void AddDataset (const GnuplotDataset& dataset); 00390 00391 /** 00392 * \param os the output stream on which the relevant gnuplot commands should 00393 * be generated. Including output file and terminal headers. 00394 */ 00395 void GenerateOutput (std::ostream &os) const; 00396 00397 private: 00398 typedef std::vector<GnuplotDataset> Datasets; 00399 00400 std::string m_outputFilename; 00401 std::string m_terminal; 00402 00403 Datasets m_datasets; 00404 00405 std::string m_title; 00406 std::string m_xLegend; 00407 std::string m_yLegend; 00408 std::string m_extra; 00409 }; 00410 00411 /** 00412 * \brief a simple class to group together multiple gnuplots into one file, 00413 * e.g. for PDF multi-page output terminals. 00414 */ 00415 class GnuplotCollection 00416 { 00417 public: 00418 /** 00419 * \param outputFilename the name of the file where the rendering of the 00420 * graph will be generated if you feed the command stream output by 00421 * GnuplotCollection::GenerateOutput to the gnuplot program. 00422 */ 00423 GnuplotCollection (const std::string& outputFilename); 00424 00425 /** 00426 * \param terminal terminal setting string for output. The default terminal 00427 * string is guessed from the output filename's extension. 00428 */ 00429 void SetTerminal (const std::string& terminal); 00430 00431 /** 00432 * \param plot add a plot to the collection to be plotted. 00433 */ 00434 void AddPlot (const Gnuplot& plot); 00435 00436 /** 00437 * Return a pointer to one of the added plots. 00438 * \param id index of plot to return 00439 * \return reference to plot, throws std::range_error if it does not exist. 00440 */ 00441 Gnuplot& GetPlot(unsigned int id); 00442 00443 /** 00444 * \param os the output stream on which the relevant gnuplot commands should 00445 * be generated. 00446 */ 00447 void GenerateOutput (std::ostream &os) const; 00448 00449 private: 00450 typedef std::vector<Gnuplot> Plots; 00451 00452 std::string m_outputFilename; 00453 std::string m_terminal; 00454 00455 Plots m_plots; 00456 }; 00457 00458 } // namespace ns3 00459 00460 #endif /* GNUPLOT_H */