1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 2 /* 3 * Copyright (c) 2007 INRIA, 2008 Timo Bingmann 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation; 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * 18 * Original Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr> 19 * Enhancements: Timo Bingmann <timo.bingmann@student.kit.edu> 20 */ 21 #ifndef GNUPLOT_H 22 #define GNUPLOT_H 23 24 #include <string> 25 #include <vector> 26 #include <utility> 27 28 namespace ns3 { 29 30 /** 31 * \ingroup gnuplot 32 * 33 * \brief Abstract class to store a plot line to be used by ns3::Gnuplot. 34 * 35 * This class contains a reference counted data object in m_data. The data 36 * object contains different structs derived from struct Data by subclasses. 37 */ 38 class GnuplotDataset 39 { 40 public: 41 42 /** 43 * Reference-counting copy constructor. 44 * \param original Original GnuPlotDataset 45 */ 46 GnuplotDataset (const GnuplotDataset& original); 47 48 /** 49 * Reference-counting destructor. 50 */ 51 ~GnuplotDataset(); 52 53 /** 54 * Reference-counting assignment operator. 55 * \param original Right-hand side of assignment operator 56 * \return Copy of original GnuplotDataset 57 */ 58 GnuplotDataset& operator= (const GnuplotDataset& original); 59 60 /** 61 * \brief Change line title. 62 * \param title the new title string to use for this dataset. 63 * 64 * \note If you want your title to contain a newline character, 65 * escape it like this: "First line\\nSecond line" so that 66 * it is converted to "First line\nSecond line" in the plot file. 67 */ 68 void SetTitle (const std::string& title); 69 70 /** 71 * \brief Change extra formatting style parameters for newly created objects. 72 * \param extra extra formatting 73 */ 74 static void SetDefaultExtra (const std::string& extra); 75 76 /** 77 * \brief Add extra formatting parameters to this dataset. 78 * \param extra extra formatting 79 */ 80 void SetExtra (const std::string& extra); 81 82 protected: 83 84 /// Friend because it accesses m_data and it's virtual functions directly in 85 /// GenerateOutput(). 86 friend class Gnuplot; 87 88 /** 89 * \brief Extra gnuplot parameters set on every newly created dataset. 90 */ 91 static std::string m_defaultExtra; 92 93 /** 94 * \brief Derived classes subclass this struct and add their own data fields. 95 */ 96 struct Data; 97 98 /** 99 * Called by constructors of derived classes. 100 * \param data the reference counted data object representing this dataset. 101 */ 102 GnuplotDataset (struct Data* data); 103 104 /** 105 * Reference counted data object. 106 */ 107 struct Data* m_data; 108 }; 109 110 /** 111 * \ingroup gnuplot 112 * 113 * \class Gnuplot2dDataset 114 * \brief Class to represent a 2D points plot. Set the line or points style 115 * using SetStyle() and set points using Add(). 116 */ 117 class Gnuplot2dDataset : public GnuplotDataset 118 { 119 public: 120 /** 121 * The plotting style to use for this dataset. 122 */ 123 enum Style { 124 LINES, 125 POINTS, 126 LINES_POINTS, 127 DOTS, 128 IMPULSES, 129 STEPS, 130 FSTEPS, 131 HISTEPS, 132 }; 133 134 /** 135 * Whether errorbars should be used for this dataset. 136 */ 137 enum ErrorBars { 138 NONE, 139 X, 140 Y, 141 XY 142 }; 143 144 /** 145 * \param title the title to be associated to this dataset. 146 * 147 * Create an empty dataset. Usually, the dataset's title is 148 * displayed in the legend box. 149 */ 150 Gnuplot2dDataset (const std::string& title = "Untitled"); 151 152 /** 153 * Change default style for all newly created objects. 154 * \param style the style of plotting to use for newly created datasets. 155 */ 156 static void SetDefaultStyle (enum Style style); 157 158 /** 159 * \param style the style of plotting to use for this dataset. 160 */ 161 void SetStyle (enum Style style); 162 163 /** 164 * Change default errorbars style for all newly created objects. 165 * \param errorBars the style of errorbars to use for newly created datasets. 166 */ 167 static void SetDefaultErrorBars (enum ErrorBars errorBars); 168 169 /** 170 * \param errorBars the style of errorbars to display. 171 * 172 * If you use any style other than none, you need 173 * to make sure you store the delta information in 174 * this dataset with the right GnuplotDataset::Add 175 * method. 176 */ 177 void SetErrorBars (enum ErrorBars errorBars); 178 179 /** 180 * \param x x coord to new data point 181 * \param y y coord to new data point 182 * 183 * Use this method with error bar style NONE. 184 */ 185 void Add (double x, double y); 186 187 /** 188 * \param x x coord to new data point 189 * \param y y coord to new data point 190 * \param errorDelta x and y data point uncertainty 191 * 192 * Use this method with error bar style X or Y. 193 */ 194 void Add (double x, double y, double errorDelta); 195 196 /** 197 * \param x x coord to new data point 198 * \param y y coord to new data point 199 * \param xErrorDelta x data point uncertainty 200 * \param yErrorDelta y data point uncertainty 201 * 202 * Use this method with error bar style XY. 203 */ 204 void Add (double x, double y, double xErrorDelta, double yErrorDelta); 205 206 /** 207 * Add an empty line in the data output sequence. Empty lines in the plot 208 * data break continuous lines and do other things in the output. 209 */ 210 void AddEmptyLine (); 211 212 private: 213 214 /** 215 * A point in a 2D plot 216 */ 217 struct Point { 218 bool empty; //!< the point is empty 219 double x; //!< X coordinate 220 double y; //!< Y coordinate 221 double dx; //!< X error delta 222 double dy; //!< Y error delta 223 }; 224 225 /// The set of points in the dataset 226 typedef std::vector<struct Point> PointSet; 227 228 static enum Style m_defaultStyle; //!< default plot style 229 static enum ErrorBars m_defaultErrorBars; //!< default error bars type 230 231 /// Forward declaration of the internal data class. 232 struct Data2d; 233 }; 234 235 /** 236 * \ingroup gnuplot 237 * 238 * \brief Class to represent a 2D function expression plot. 239 * 240 * Since the function expression is not escaped, styles and extras could just 241 * as well be included in the expression string. 242 */ 243 class Gnuplot2dFunction : public GnuplotDataset 244 { 245 public: 246 /** 247 * \param title the title to be associated to this dataset. 248 * \param function function to plot 249 * 250 * Create an function dataset. Usually, the dataset's title is displayed in 251 * the legend box. 252 */ 253 Gnuplot2dFunction (const std::string& title = "Untitled", const std::string& function = ""); 254 255 /** 256 * \param function new function string to set 257 */ 258 void SetFunction (const std::string& function); 259 260 private: 261 262 /// Forward declaration of the internal data class. 263 struct Function2d; 264 }; 265 266 /** 267 * \ingroup gnuplot 268 * 269 * \brief Class to represent a 3D points plot. Set the line or points style 270 * using SetStyle() and set points using Add(). 271 */ 272 class Gnuplot3dDataset : public GnuplotDataset 273 { 274 public: 275 /** 276 * \param title the title to be associated to this dataset. 277 * 278 * Create an empty dataset. Usually, the dataset's title is 279 * displayed in the legend box. 280 */ 281 Gnuplot3dDataset (const std::string& title = "Untitled"); 282 283 /** 284 * Change default style for all newly created objects. 285 * \param style the style of plotting to use for newly created datasets. 286 */ 287 static void SetDefaultStyle (const std::string& style); 288 289 /** 290 * \param style the style of plotting to use for this dataset. 291 */ 292 void SetStyle (const std::string& style); 293 294 /** 295 * \param x x coord to new data point 296 * \param y y coord to new data point 297 * \param z z coord to new data point 298 * 299 * Use this method to add a new 3D point 300 */ 301 void Add (double x, double y, double z); 302 303 /** 304 * Add an empty line in the data output sequence. Empty lines in the plot 305 * data break continuous lines and do other things in the output. 306 */ 307 void AddEmptyLine (); 308 309 private: 310 311 /** 312 * A point in a 3D plot 313 */ 314 struct Point { 315 bool empty; //!< the point is empty 316 double x; //!< X coordinate 317 double y; //!< Y coordinate 318 double z; //!< Z coordinate 319 }; 320 321 /// The set of points in the dataset 322 typedef std::vector<struct Point> PointSet; 323 324 static std::string m_defaultStyle; //!< default plot style 325 326 /// Forward declaration of the internal data class. 327 struct Data3d; 328 }; 329 330 /** 331 * \ingroup gnuplot 332 * 333 * \brief Class to represent a 3D function expression plot. 334 * 335 * Since the function expression is not escaped, styles and extras could just as 336 * well be included in the expression string. The only difference to 337 * Gnuplot2dFunction is the splot command string. 338 */ 339 class Gnuplot3dFunction : public GnuplotDataset 340 { 341 public: 342 /** 343 * \param title the title to be associated to this dataset. 344 * \param function function to plot 345 * 346 * Create an function dataset. Usually, the dataset's title is displayed in 347 * the legend box. 348 */ 349 Gnuplot3dFunction (const std::string& title = "Untitled", const std::string& function = ""); 350 351 /** 352 * \param function new function string to set 353 */ 354 void SetFunction (const std::string& function); 355 356 private: 357 358 /// Forward declaration of the internal data class. 359 struct Function3d; 360 }; 361 362 /** 363 * \ingroup gnuplot 364 * 365 * \brief a simple class to generate gnuplot-ready plotting commands 366 * from a set of datasets. 367 * 368 * This class really represents a single graph on which multiple datasets 369 * can be plotted. 370 */ 371 class Gnuplot 372 { 373 public: 374 /** 375 * \param outputFilename the name of the file where the rendering of the 376 * graph will be generated if you feed the command stream output by 377 * Gnuplot::GenerateOutput to the gnuplot program. 378 * \param title title line of the plot page 379 */ 380 Gnuplot (const std::string& outputFilename="", const std::string& title = ""); 381 382 /** 383 * \param outputFilename the name of the file where the rendering of the 384 * graph will be generated if you feed the command stream output by 385 * Gnuplot::GenerateOutput to the gnuplot program. 386 */ 387 void SetOutputFilename (const std::string& outputFilename); 388 389 /** 390 * Crude attempt to auto-detect the correct terminal setting by inspecting 391 * the filename's extension. 392 * \param filename output filename 393 * \return File extension of the provided filename 394 */ 395 static std::string DetectTerminal (const std::string& filename); 396 397 /** 398 * \param terminal terminal setting string for output. The default terminal 399 * string is "png" 400 */ 401 void SetTerminal (const std::string& terminal); 402 403 /** 404 * \param title set new plot title string to use for this plot. 405 */ 406 void SetTitle (const std::string& title); 407 408 /** 409 * \param xLegend the legend for the x horizontal axis 410 * \param yLegend the legend for the y vertical axis 411 */ 412 void SetLegend (const std::string& xLegend, const std::string& yLegend); 413 414 /** 415 * \param extra set extra gnuplot directive for output. 416 */ 417 void SetExtra (const std::string& extra); 418 419 /** 420 * \param extra append extra gnuplot directive for output. 421 */ 422 void AppendExtra (const std::string& extra); 423 424 /** 425 * \param dataset add a dataset to the graph to be plotted. 426 */ 427 void AddDataset (const GnuplotDataset& dataset); 428 429 /** 430 * \param os the output stream on which the relevant gnuplot 431 * commands should be generated. Including output file and terminal 432 * headers. 433 * 434 * \brief Writes gnuplot commands and data values to a single 435 * output stream. 436 */ 437 void GenerateOutput (std::ostream &os); 438 439 /** 440 * \param osControl the output stream on which the relevant gnuplot 441 * control commands should be generated. Including output file and 442 * terminal headers. 443 * \param osData the output stream on which the relevant gnuplot 444 * data values should be generated. 445 * \param dataFileName the name for the data file that will be 446 * written. 447 * 448 * \brief Writes gnuplot commands and data values to two 449 * different outputs streams. 450 */ 451 void GenerateOutput (std::ostream &osControl, 452 std::ostream &osData, 453 std::string dataFileName); 454 455 /** 456 * \param index the index for the data stream in the data file. 457 * 458 * \brief Sets the current data stream index in the data file. 459 */ 460 void SetDataFileDatasetIndex (unsigned int index); 461 462 private: 463 /// Type for Datasets to be used in plots 464 typedef std::vector<GnuplotDataset> Datasets; 465 466 std::string m_outputFilename; //!< Output file name 467 std::string m_terminal; //!< Gnuplot "terminal" to use 468 469 Datasets m_datasets; //!< Data sets 470 471 std::string m_title; //!< Plot title 472 std::string m_xLegend; //!< X axis legend 473 std::string m_yLegend; //!< Y axis legend 474 std::string m_extra; //!< extra parameters for the plot 475 476 bool m_generateOneOutputFile; //!< true if only one plot will be generated 477 478 unsigned int m_dataFileDatasetIndex; //!< Data set index to plot 479 }; 480 481 /** 482 * \ingroup gnuplot 483 * 484 * \brief a simple class to group together multiple gnuplots into one file, 485 * e.g. for PDF multi-page output terminals. 486 */ 487 class GnuplotCollection 488 { 489 public: 490 /** 491 * \param outputFilename the name of the file where the rendering of the 492 * graph will be generated if you feed the command stream output by 493 * GnuplotCollection::GenerateOutput to the gnuplot program. 494 */ 495 GnuplotCollection (const std::string& outputFilename); 496 497 /** 498 * \param terminal terminal setting string for output. The default terminal 499 * string is guessed from the output filename's extension. 500 */ 501 void SetTerminal (const std::string& terminal); 502 503 /** 504 * \param plot add a plot to the collection to be plotted. 505 */ 506 void AddPlot (const Gnuplot& plot); 507 508 /** 509 * Return a pointer to one of the added plots. 510 * \param id index of plot to return 511 * \return reference to plot, throws std::range_error if it does not exist. 512 */ 513 Gnuplot& GetPlot (unsigned int id); 514 515 /** 516 * \param os the output stream on which the relevant gnuplot commands should 517 * be generated. 518 */ 519 void GenerateOutput (std::ostream &os); 520 521 /** 522 * \param osControl the output stream on which the relevant gnuplot 523 * control commands should be generated. Including output file and 524 * terminal headers. 525 * \param osData the output stream on which the relevant gnuplot 526 * data values should be generated. 527 * \param dataFileName the name for the data file that will be 528 * written. 529 */ 530 void GenerateOutput (std::ostream &osControl, 531 std::ostream &osData, 532 std::string dataFileName); 533 534 private: 535 /// Type of the Gnuplot collection 536 typedef std::vector<Gnuplot> Plots; 537 538 std::string m_outputFilename; //!< Output file name 539 std::string m_terminal; //!< Gnuplot "terminal" to use 540 541 Plots m_plots; //!< Plots in the collection 542 }; 543 544 } // namespace ns3 545 546 #endif /* GNUPLOT_H */ 547