A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
gnuplot.cc
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 #include "gnuplot.h"
22 #include "ns3/assert.h"
23 #include <ostream>
24 #include <stdexcept>
25 
26 namespace ns3 {
27 
28 // --- GnuplotDataset::Data ------------------------------------------------ //
29 
31 {
32  // *** Data Variables ***
33 
34  unsigned int m_references;
35 
36  std::string m_title;
37  std::string m_extra;
38 
42  Data(const std::string& title);
43 
45  virtual ~Data();
46 
50  virtual std::string GetCommand () const = 0;
51 
57  virtual void PrintExpression (std::ostream &os) const = 0;
58 
63  virtual void PrintDatafile (std::ostream &os) const = 0;
64 };
65 
66 GnuplotDataset::Data::Data(const std::string& title)
67  : m_references (1),
68  m_title (title),
69  m_extra (m_defaultExtra)
70 {
71 }
72 
74 {
75 }
76 
77 // --- GnuplotDataset ------------------------------------------------------ //
78 
79 std::string GnuplotDataset::m_defaultExtra = "";
80 
82  : m_data (data)
83 {
84 }
85 
87  : m_data (original.m_data)
88 {
89  ++m_data->m_references;
90 }
91 
93 {
94  if (--m_data->m_references == 0)
95  delete m_data;
96 }
97 
99 {
100  if (this != &original)
101  {
102  if (--m_data->m_references == 0)
103  delete m_data;
104 
105  m_data = original.m_data;
106  ++m_data->m_references;
107  }
108  return *this;
109 }
110 
111 void
112 GnuplotDataset::SetTitle (const std::string& title)
113 {
114  m_data->m_title = title;
115 }
116 
117 void
118 GnuplotDataset::SetDefaultExtra (const std::string& extra)
119 {
120  m_defaultExtra = extra;
121 }
122 void
123 GnuplotDataset::SetExtra (const std::string& extra)
124 {
125  m_data->m_extra = extra;
126 }
127 
128 // --- Gnuplot2dDataset::Data2d -------------------------------------------- //
129 
131 {
132  // *** Data Variables ***
133 
134  enum Style m_style;
135  enum ErrorBars m_errorBars;
136 
137  PointSet m_pointset;
138 
142  Data2d(const std::string& title);
143 
144  virtual std::string GetCommand () const;
145  virtual void PrintExpression (std::ostream &os) const;
146  virtual void PrintDatafile (std::ostream &os) const;
147 };
148 
149 Gnuplot2dDataset::Data2d::Data2d(const std::string& title)
150  : Data (title),
151  m_style (m_defaultStyle),
152  m_errorBars (m_defaultErrorBars)
153 {
154 }
155 
156 std::string
158 {
159  return "plot";
160 }
161 
162 void
164 {
165  os << "'-' ";
166 
167  if (m_title.size ())
168  os << " title '" << m_title << "'";
169 
170  switch (m_style) {
171  case LINES:
172  os << " with lines";
173  break;
174  case POINTS:
175  switch (m_errorBars)
176  {
177  case NONE:
178  os << " with points";
179  break;
180  case X:
181  os << " with xerrorbars";
182  break;
183  case Y:
184  os << " with yerrorbars";
185  break;
186  case XY:
187  os << " with xyerrorbars";
188  break;
189  }
190  break;
191  case LINES_POINTS:
192  switch (m_errorBars)
193  {
194  case NONE:
195  os << " with linespoints";
196  break;
197  case X:
198  os << " with errorlines";
199  break;
200  case Y:
201  os << " with yerrorlines";
202  break;
203  case XY:
204  os << " with xyerrorlines";
205  break;
206  }
207  break;
208  case DOTS:
209  os << " with dots";
210  break;
211  case IMPULSES:
212  os << " with impulses";
213  break;
214  case STEPS:
215  os << " with steps";
216  break;
217  case FSTEPS:
218  os << " with fsteps";
219  break;
220  case HISTEPS:
221  os << " with histeps";
222  break;
223  }
224 
225  if (m_extra.size ())
226  os << " " << m_extra;
227 }
228 
229 void
231 {
232  for (PointSet::const_iterator i = m_pointset.begin ();
233  i != m_pointset.end (); ++i)
234  {
235  if (i->empty) {
236  os << std::endl;
237  continue;
238  }
239 
240  switch (m_errorBars) {
241  case NONE:
242  os << i->x << " " << i->y << std::endl;
243  break;
244  case X:
245  os << i->x << " " << i->y << " " << i->dx << std::endl;
246  break;
247  case Y:
248  os << i->x << " " << i->y << " " << i->dy << std::endl;
249  break;
250  case XY:
251  os << i->x << " " << i->y << " " << i->dx << " " << i->dy << std::endl;
252  break;
253  }
254  }
255  os << "e" << std::endl;
256 }
257 
258 // --- Gnuplot2dDataset ---------------------------------------------------- //
259 
260 enum Gnuplot2dDataset::Style Gnuplot2dDataset::m_defaultStyle = LINES;
261 enum Gnuplot2dDataset::ErrorBars Gnuplot2dDataset::m_defaultErrorBars = NONE;
262 
263 Gnuplot2dDataset::Gnuplot2dDataset (const std::string& title)
264  : GnuplotDataset ( new Data2d (title) )
265 {
266 }
267 
268 void
270 {
271  m_defaultStyle = style;
272 }
273 void
275 {
276  reinterpret_cast<Data2d*>(m_data)->m_style = style;
277 }
278 
279 void
281 {
282  m_defaultErrorBars = errorBars;
283 }
284 void
286 {
287  reinterpret_cast<Data2d*>(m_data)->m_errorBars = errorBars;
288 }
289 
290 void
291 Gnuplot2dDataset::Add (double x, double y)
292 {
293  NS_ASSERT (reinterpret_cast<Data2d*>(m_data)->m_errorBars == NONE);
294 
295  struct Point data;
296  data.empty = false;
297  data.x = x;
298  data.y = y;
299  data.dx = 0.0;
300  data.dy = 0.0;
301  reinterpret_cast<Data2d*>(m_data)->m_pointset.push_back (data);
302 }
303 
304 void
305 Gnuplot2dDataset::Add (double x, double y, double errorDelta)
306 {
307  NS_ASSERT ( reinterpret_cast<Data2d*>(m_data)->m_errorBars == X ||
308  reinterpret_cast<Data2d*>(m_data)->m_errorBars == Y );
309 
310  struct Point data;
311  data.empty = false;
312  data.x = x;
313  data.y = y;
314  data.dx = errorDelta;
315  data.dy = errorDelta;
316  reinterpret_cast<Data2d*>(m_data)->m_pointset.push_back (data);
317 }
318 
319 void
320 Gnuplot2dDataset::Add (double x, double y, double xErrorDelta, double yErrorDelta)
321 {
322  NS_ASSERT ( reinterpret_cast<Data2d*>(m_data)->m_errorBars == XY );
323 
324  struct Point data;
325  data.empty = false;
326  data.x = x;
327  data.y = y;
328  data.dx = xErrorDelta;
329  data.dy = yErrorDelta;
330  reinterpret_cast<Data2d*>(m_data)->m_pointset.push_back (data);
331 }
332 
333 void
335 {
336  struct Point data;
337  data.empty = true;
338  reinterpret_cast<Data2d*>(m_data)->m_pointset.push_back (data);
339 }
340 
341 // --- Gnuplot2dFunction::Function2d --------------------------------------- //
342 
344 {
345  // *** Data Variables ***
346 
347  std::string m_function;
348 
352  Function2d(const std::string& title, const std::string& function);
353 
354  virtual std::string GetCommand () const;
355  virtual void PrintExpression (std::ostream &os) const;
356  virtual void PrintDatafile (std::ostream &os) const;
357 };
358 
359 Gnuplot2dFunction::Function2d::Function2d(const std::string& title, const std::string& function)
360  : Data (title),
361  m_function (function)
362 {
363 }
364 
365 std::string
367 {
368  return "plot";
369 }
370 
371 void
373 {
374  os << m_function;
375 
376  if (m_title.size ())
377  os << " title '" << m_title << "'";
378 
379  if (m_extra.size ())
380  os << " " << m_extra;
381 }
382 
383 void
385 {
386 }
387 
388 // --- Gnuplot2dFunction --------------------------------------------------- //
389 
390 Gnuplot2dFunction::Gnuplot2dFunction (const std::string& title, const std::string& function)
391  : GnuplotDataset ( new Function2d (title, function) )
392 {
393 }
394 
395 void
396 Gnuplot2dFunction::SetFunction (const std::string& function)
397 {
398  reinterpret_cast<Function2d*>(m_data)->m_function = function;
399 }
400 
401 // --- Gnuplot3dDataset::Data3d -------------------------------------------- //
402 
404 {
405  // *** Data Variables ***
406 
407  std::string m_style;
408 
409  PointSet m_pointset;
410 
414  Data3d(const std::string& title);
415 
416  virtual std::string GetCommand () const;
417  virtual void PrintExpression (std::ostream &os) const;
418  virtual void PrintDatafile (std::ostream &os) const;
419 };
420 
421 Gnuplot3dDataset::Data3d::Data3d(const std::string& title)
422  : Data (title),
423  m_style (m_defaultStyle)
424 {
425 }
426 
427 std::string
429 {
430  return "splot";
431 }
432 
433 void
435 {
436  os << "'-' ";
437 
438  if (m_style.size ())
439  os << " " << m_style;
440 
441  if (m_title.size ())
442  os << " title '" << m_title << "'";
443 
444  if (m_extra.size ())
445  os << " " << m_extra;
446 }
447 
448 void
450 {
451  for (PointSet::const_iterator i = m_pointset.begin ();
452  i != m_pointset.end (); ++i)
453  {
454  if (i->empty) {
455  os << std::endl;
456  continue;
457  }
458 
459  os << i->x << " " << i->y << " " << i->z << std::endl;
460  }
461  os << "e" << std::endl;
462 }
463 
464 // --- Gnuplot3dDataset ---------------------------------------------------- //
465 
466 std::string Gnuplot3dDataset::m_defaultStyle = "";
467 
468 Gnuplot3dDataset::Gnuplot3dDataset (const std::string& title)
469  : GnuplotDataset ( new Data3d (title) )
470 {
471 }
472 
473 void
474 Gnuplot3dDataset::SetDefaultStyle (const std::string& style)
475 {
476  m_defaultStyle = style;
477 }
478 void
479 Gnuplot3dDataset::SetStyle (const std::string& style)
480 {
481  reinterpret_cast<Data3d*>(m_data)->m_style = style;
482 }
483 
484 void
485 Gnuplot3dDataset::Add (double x, double y, double z)
486 {
487  struct Point data;
488  data.empty = false;
489  data.x = x;
490  data.y = y;
491  data.z = z;
492  reinterpret_cast<Data3d*>(m_data)->m_pointset.push_back (data);
493 }
494 
495 void
497 {
498  struct Point data;
499  data.empty = true;
500  reinterpret_cast<Data3d*>(m_data)->m_pointset.push_back (data);
501 }
502 
503 // --- Gnuplot3dFunction::Function3d --------------------------------------- //
504 
506 {
507  // *** Data Variables ***
508 
509  std::string m_function;
510 
514  Function3d(const std::string& title, const std::string& function);
515 
516  virtual std::string GetCommand () const;
517  virtual void PrintExpression (std::ostream &os) const;
518  virtual void PrintDatafile (std::ostream &os) const;
519 };
520 
521 Gnuplot3dFunction::Function3d::Function3d(const std::string& title, const std::string& function)
522  : Data (title),
523  m_function (function)
524 {
525 }
526 
527 std::string
529 {
530  return "splot";
531 }
532 
533 void
535 {
536  os << m_function;
537 
538  if (m_title.size ())
539  os << " title '" << m_title << "'";
540 
541  if (m_extra.size ())
542  os << " " << m_extra;
543 }
544 
545 void
547 {
548 }
549 
550 // --- Gnuplot3dFunction --------------------------------------------------- //
551 
552 Gnuplot3dFunction::Gnuplot3dFunction (const std::string& title, const std::string& function)
553  : GnuplotDataset ( new Function3d (title, function) )
554 {
555 }
556 
557 void
558 Gnuplot3dFunction::SetFunction (const std::string& function)
559 {
560  reinterpret_cast<Function3d*>(m_data)->m_function = function;
561 }
562 
563 // ------------------------------------------------------------------------- //
564 
565 Gnuplot::Gnuplot (const std::string& outputFilename, const std::string& title)
566  : m_outputFilename (outputFilename),
567  m_terminal ( DetectTerminal (outputFilename) ),
568  m_title (title)
569 {
570 }
571 
572 std::string Gnuplot::DetectTerminal (const std::string& filename)
573 {
574  std::string::size_type dotpos = filename.rfind ('.');
575  if (dotpos == std::string::npos) return "";
576 
577  if (filename.substr (dotpos) == ".png") {
578  return "png";
579  }
580  else if (filename.substr (dotpos) == ".pdf") {
581  return "pdf";
582  }
583 
584  return "";
585 }
586 
587 void
588 Gnuplot::SetTerminal (const std::string& terminal)
589 {
590  m_terminal = terminal;
591 }
592 
593 void
594 Gnuplot::SetTitle (const std::string& title)
595 {
596  m_title = title;
597 }
598 
599 void
600 Gnuplot::SetLegend (const std::string& xLegend, const std::string& yLegend)
601 {
602  m_xLegend = xLegend;
603  m_yLegend = yLegend;
604 }
605 
606 void
607 Gnuplot::SetExtra (const std::string& extra)
608 {
609  m_extra = extra;
610 }
611 
612 void
613 Gnuplot::AppendExtra (const std::string& extra)
614 {
615  m_extra += "\n";
616  m_extra += extra;
617 }
618 
619 void
621 {
622  m_datasets.push_back (dataset);
623 }
624 
625 void
626 Gnuplot::GenerateOutput (std::ostream &os) const
627 {
628  if (m_terminal.size ())
629  os << "set terminal " << m_terminal << std::endl;
630 
631  if (m_outputFilename.size ())
632  os << "set output '" << m_outputFilename << "'" << std::endl;
633 
634  if (m_title.size ())
635  os << "set title '" << m_title << "'" << std::endl;
636 
637  if (m_xLegend.size ())
638  os << "set xlabel '" << m_xLegend << "'" << std::endl;
639 
640  if (m_yLegend.size ())
641  os << "set ylabel '" << m_yLegend << "'" << std::endl;
642 
643  if (m_extra.size ())
644  os << m_extra << std::endl;
645 
646  if (m_datasets.empty ())
647  return;
648 
649  // Determine the GetCommand() values of all datasets included. Check that all
650  // are equal and print the command.
651 
652  std::string command = m_datasets.begin ()->m_data->GetCommand ();
653 
654  for (Datasets::const_iterator i = m_datasets.begin () + 1;
655  i != m_datasets.end (); ++i)
656  {
657  NS_ASSERT_MSG (command == i->m_data->GetCommand (),
658  "Cannot mix 'plot' and 'splot' GnuplotDatasets.");
659  }
660 
661  os << command << " ";
662 
663  // Print all dataset expressions
664 
665  for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end ();)
666  {
667  i->m_data->PrintExpression (os);
668 
669  i++;
670 
671  if (i != m_datasets.end ())
672  {
673  os << ", ";
674  }
675  }
676  os << std::endl;
677 
678  // followed by the inline datafile.
679 
680  for (Datasets::const_iterator i = m_datasets.begin (); i != m_datasets.end (); i++)
681  {
682  i->m_data->PrintDatafile (os);
683  }
684 }
685 
686 // ------------------------------------------------------------------------- //
687 
688 GnuplotCollection::GnuplotCollection (const std::string& outputFilename)
689  : m_outputFilename (outputFilename),
690  m_terminal ( Gnuplot::DetectTerminal (outputFilename) )
691 {
692 }
693 
694 void
695 GnuplotCollection::SetTerminal (const std::string& terminal)
696 {
697  m_terminal = terminal;
698 }
699 
700 void
702 {
703  m_plots.push_back (plot);
704 }
705 
706 Gnuplot&
707 GnuplotCollection::GetPlot (unsigned int id)
708 {
709  if (id >= m_plots.size ())
710  throw(std::range_error ("Gnuplot id is out of range"));
711  else
712  return m_plots[id];
713 }
714 
715 void
716 GnuplotCollection::GenerateOutput (std::ostream &os) const
717 {
718  if (m_terminal.size ())
719  os << "set terminal " << m_terminal << std::endl;
720 
721  if (m_outputFilename.size ())
722  os << "set output '" << m_outputFilename << "'" << std::endl;
723 
724  for (Plots::const_iterator i = m_plots.begin (); i != m_plots.end (); ++i)
725  {
726  i->GenerateOutput (os);
727  }
728 }
729 
730 // ------------------------------------------------------------------------- //
731 
732 } // namespace ns3
virtual void PrintDatafile(std::ostream &os) const
Definition: gnuplot.cc:230
void AppendExtra(const std::string &extra)
Definition: gnuplot.cc:613
Function3d(const std::string &title, const std::string &function)
Definition: gnuplot.cc:521
void SetTitle(const std::string &title)
Change line title.
Definition: gnuplot.cc:112
virtual void PrintExpression(std::ostream &os) const =0
Abstract class to store a plot line to be used by ns3::Gnuplot.
Definition: gnuplot.h:38
Gnuplot(const std::string &outputFilename="", const std::string &title="")
Definition: gnuplot.cc:565
virtual void PrintDatafile(std::ostream &os) const =0
Gnuplot2dDataset(const std::string &title="Untitled")
Definition: gnuplot.cc:263
void GenerateOutput(std::ostream &os) const
Definition: gnuplot.cc:626
static void SetDefaultExtra(const std::string &extra)
Change extra formatting style parameters for newly created objects.
Definition: gnuplot.cc:118
void Add(double x, double y, double z)
Definition: gnuplot.cc:485
#define NS_ASSERT(condition)
Definition: assert.h:64
GnuplotDataset & operator=(const GnuplotDataset &original)
Definition: gnuplot.cc:98
virtual std::string GetCommand() const
Definition: gnuplot.cc:157
static std::string m_defaultExtra
Extra gnuplot parameters set on every newly created dataset.
Definition: gnuplot.h:84
void SetFunction(const std::string &function)
Definition: gnuplot.cc:396
void AddDataset(const GnuplotDataset &dataset)
Definition: gnuplot.cc:620
Data3d(const std::string &title)
Definition: gnuplot.cc:421
void SetExtra(const std::string &extra)
Add extra formatting parameters to this dataset.
Definition: gnuplot.cc:123
void SetErrorBars(enum ErrorBars errorBars)
Definition: gnuplot.cc:285
virtual std::string GetCommand() const
Definition: gnuplot.cc:366
struct Data * m_data
Definition: gnuplot.h:100
Data2d(const std::string &title)
Definition: gnuplot.cc:149
a simple class to generate gnuplot-ready plotting commands from a set of datasets.
Definition: gnuplot.h:343
void SetTitle(const std::string &title)
Definition: gnuplot.cc:594
Gnuplot3dDataset(const std::string &title="Untitled")
Definition: gnuplot.cc:468
Function2d(const std::string &title, const std::string &function)
Definition: gnuplot.cc:359
void Add(double x, double y)
Definition: gnuplot.cc:291
Gnuplot2dFunction(const std::string &title="Untitled", const std::string &function="")
Definition: gnuplot.cc:390
Gnuplot3dFunction(const std::string &title="Untitled", const std::string &function="")
Definition: gnuplot.cc:552
void AddPlot(const Gnuplot &plot)
Definition: gnuplot.cc:701
void SetLegend(const std::string &xLegend, const std::string &yLegend)
Definition: gnuplot.cc:600
static void SetDefaultErrorBars(enum ErrorBars errorBars)
Definition: gnuplot.cc:280
virtual std::string GetCommand() const =0
GnuplotCollection(const std::string &outputFilename)
Definition: gnuplot.cc:688
static void SetDefaultStyle(enum Style style)
Definition: gnuplot.cc:269
virtual void PrintDatafile(std::ostream &os) const
Definition: gnuplot.cc:546
void SetStyle(enum Style style)
Definition: gnuplot.cc:274
void SetExtra(const std::string &extra)
Definition: gnuplot.cc:607
void SetStyle(const std::string &style)
Definition: gnuplot.cc:479
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
void SetTerminal(const std::string &terminal)
Definition: gnuplot.cc:695
virtual void PrintExpression(std::ostream &os) const
Definition: gnuplot.cc:534
void SetFunction(const std::string &function)
Definition: gnuplot.cc:558
virtual void PrintExpression(std::ostream &os) const
Definition: gnuplot.cc:372
virtual std::string GetCommand() const
Definition: gnuplot.cc:428
virtual void PrintExpression(std::ostream &os) const
Definition: gnuplot.cc:434
GnuplotDataset(const GnuplotDataset &original)
Definition: gnuplot.cc:86
virtual std::string GetCommand() const
Definition: gnuplot.cc:528
virtual void PrintDatafile(std::ostream &os) const
Definition: gnuplot.cc:384
static void SetDefaultStyle(const std::string &style)
Definition: gnuplot.cc:474
static std::string DetectTerminal(const std::string &filename)
Definition: gnuplot.cc:572
void SetTerminal(const std::string &terminal)
Definition: gnuplot.cc:588
Data(const std::string &title)
Definition: gnuplot.cc:66
virtual ~Data()
Required.
Definition: gnuplot.cc:73
virtual void PrintExpression(std::ostream &os) const
Definition: gnuplot.cc:163
void GenerateOutput(std::ostream &os) const
Definition: gnuplot.cc:716
Gnuplot & GetPlot(unsigned int id)
Definition: gnuplot.cc:707
virtual void PrintDatafile(std::ostream &os) const
Definition: gnuplot.cc:449