ns-3的绘图工具——Gnuplot

对仿真数据进行统计分析,并做成图表可以更加直观地体现协议的性能。本文将介绍如何使用Gnuplot把ns-3仿真程序捕获的数据做成图表。

使用ns-3和gnuplot绘制图形有两种常用方法(http://www.gnuplot.info):

  1. 使用ns-3的gnuplot类创建gnuplot控制文件。
  2. 使用ns-3生成的值创建gnuplot数据文件。

这里主要介绍方法1,即如何使用ns-3的gnuplot类绘制图。如果对方法2感兴趣,请参阅NS-3Tutorial中“Tracing”部分的“A Real Example”小节。

1.Gnuplot

gnuplot是一个命令行驱动的交互式绘图工具(command-driven interactive function plotting program),可将数学函数或数值资料以平面图或立体图的形式画在不同种类终端机或绘图输出装置上。它是由Colin Kelley 和 Thomas Williams于1986年开发的绘图程序发展而来的,可以在多个平台下使用。gnuplot既支持命令行交互模式,也支持脚本。

如果Ubuntu中尚未安装Gnuplot,使用如下命令安装:

sudo apt-get install gnuplot

安装完成之后进行测试。输入gnuplot进入交互式界面。
输入如下命令:plot[-3.14:3.14]sin(x),如下图所示:
ns-3的绘图工具——Gnuplot得到如下的正弦曲线:
ns-3的绘图工具——Gnuplot

2.Gnuplot类

ns-3为了能生成Gnuploy数据图表提供了一组和Gnuplot连接的类,包含在头文件ns3/gnuplot.h中,可分成两类。

(1)Gnuplot类:是ns-3和Gnuplot连接的重要接口,其功能包括:设置文件名,坐标,标题,添加数据集,生成文件等。
ns-3的绘图工具——Gnuplot
(2)GnuplotDataset类:只是一个数据集,存储plot数据供Gnuplot使用。
ns-3的绘图工具——Gnuplot
可参考https://www.nsnam.org/docs/release/3.29/doxygen/classns3_1_1_gnuplot.html

3.使用Gnuplot

必须采取以下步骤才能使用ns-3的gnuplot类创建绘图:

  1. 修改代码,以便使用gnuplot类及其函数。
  2. 运行代码,以创建gnuplot控制文件。
  3. 使用gnuplot控制文件的名称调用gnuplot。
  4. 在任意图片查看器中浏览生成的图形文件。

下面使用示例src/stats/examples/gnuplot-example.cc来演示Gnuplot类和Gnuplot工具的使用。

1)运行例子
[email protected]:~/tarballs/ns-allinone-3.29/ns-3.29$ ./waf --run src/stats/examples/gnuplot-example

2)程序运行后生成Gnuplot控制文件
plot-2d.plt
plot-2d-with-error-bars.plt
plot-3d.plt
ns-3的绘图工具——Gnuplot
3)使用Gnuplot处理Gnuplot控制文件

$ gnuplot plot-2d.plt
$ gnuplot plot-2d-with-error-bars.plt
$ gnuplot plot-3d.plt

4)处理后生成图片文件
plot-2d.png
plot-2d-with-error-bars.png
plot-3d.png

5.)打开图片文件
ns-3的绘图工具——Gnuplotns-3的绘图工具——Gnuplotns-3的绘图工具——Gnuplot
下面是具体的代码分析:

#include <fstream>

#include "ns3/gnuplot.h"        //包含gnuplot.h头文件

using namespace ns3;            //声明命名空间

namespace {

//===========================================================================
// Function: Create2DPlotFile
// This function creates a 2-D plot file.
// 生成二维图的函数
// 由于使用ns-3命名空间,所有标准C++要加上std::前缀
//===========================================================================
void Create2DPlotFile ()
{
  std::string fileNameWithNoExtension = "plot-2d";
  std::string graphicsFileName        = fileNameWithNoExtension + ".png";
  std::string plotFileName            = fileNameWithNoExtension + ".plt";
  std::string plotTitle               = "2-D Plot";
  std::string dataTitle               = "2-D Data";

  // 安装plot并设置其标题
  Gnuplot plot (graphicsFileName);
  plot.SetTitle (plotTitle);

  // 设置文件格式
  // 使绘图文件与gnuplot一起使用时将创建的图形文件成为PNG文件。
  plot.SetTerminal ("png");

  // 设置坐标标签
  plot.SetLegend ("X Values", "Y Values");

  // 设置坐标范围
  plot.AppendExtra ("set xrange [-6:+6]");

  // 初始化数据集,设置标题和风格
  // 点与连接线一起绘制
  Gnuplot2dDataset dataset;
  dataset.SetTitle (dataTitle);
  dataset.SetStyle (Gnuplot2dDataset::LINES_POINTS);

  double x;
  double y;

  // 生成二维数据集
  for (x = -5.0; x <= +5.0; x += 1.0)
    {
      // 图形曲线
      y = x * x;

      // 向数据集中添加坐标
      dataset.Add (x, y);
    }

  // 把数据集添加到Gnuplot对象
  plot.AddDataset (dataset);

  // 打开plot文件
  std::ofstream plotFile (plotFileName.c_str());

  // 写plot文件
  plot.GenerateOutput (plotFile);

  // 关闭plot文件
  plotFile.close ();
}


//===========================================================================
// Function: Create2DPlotWithErrorBarsFile
// This function creates a 2-D plot with error bars file.
// 生成带有误差线的二维图的函数
//===========================================================================

void Create2DPlotWithErrorBarsFile ()
{
  std::string fileNameWithNoExtension = "plot-2d-with-error-bars";
  std::string graphicsFileName        = fileNameWithNoExtension + ".png";
  std::string plotFileName            = fileNameWithNoExtension + ".plt";
  std::string plotTitle               = "2-D Plot With Error Bars";
  std::string dataTitle               = "2-D Data With Error Bars";

  // 安装plot并设置其标题
  Gnuplot plot (graphicsFileName);
  plot.SetTitle (plotTitle);

  // 设置文件格式
  // 使绘图文件与gnuplot一起使用时将创建的图形文件成为PNG文件。
  plot.SetTerminal ("png");

  // 设置坐标标签
  plot.SetLegend ("X Values", "Y Values");

  // 设置坐标范围
  plot.AppendExtra ("set xrange [-6:+6]");

  // 初始化数据集,设置标题和风格
  // 只绘制点,无连接线
  Gnuplot2dDataset dataset;
  dataset.SetTitle (dataTitle);
  dataset.SetStyle (Gnuplot2dDataset::POINTS);

  // 使数据集在X和Y方向都有误差线
  dataset.SetErrorBars (Gnuplot2dDataset::XY);

  double x;
  double xErrorDelta;
  double y;
  double yErrorDelta;

  // 生成二维数据集
  for (x = -5.0; x <= +5.0; x += 1.0)
    {
      // 图形曲线
      y = x * x;

      // 使X方向的不确定性保持不变,使Y方向的不确定性成为其取值的一个恒定比值
      xErrorDelta = 0.25;
      yErrorDelta = 0.1 * y;

      // 在x和y方向添加这个不确定点
      dataset.Add (x, y, xErrorDelta, yErrorDelta);
    }

  // 把数据集添加到Gnuplot对象
  plot.AddDataset (dataset);

  // 打开plot文件
  std::ofstream plotFile (plotFileName.c_str());

  // 写plot文件
  plot.GenerateOutput (plotFile);

  // 关闭plot文件
  plotFile.close ();
}


//===========================================================================
// Function: Create3DPlotFile
// This function creates a 3-D plot file.
// 生成三维图的函数
//===========================================================================

void Create3DPlotFile ()
{
  std::string fileNameWithNoExtension = "plot-3d";
  std::string graphicsFileName        = fileNameWithNoExtension + ".png";
  std::string plotFileName            = fileNameWithNoExtension + ".plt";
  std::string plotTitle               = "3-D Plot";
  std::string dataTitle               = "3-D Data";

  // 安装plot并设置其标题
  Gnuplot plot (graphicsFileName);
  plot.SetTitle (plotTitle);

  // 设置文件格式
  // 使绘图文件与gnuplot一起使用时将创建的图形文件成为PNG文件。
  plot.SetTerminal ("png");

  // 围绕X轴旋转30度,然后围绕新Z轴旋转120度
  plot.AppendExtra ("set view 30, 120, 1.0, 1.0");

  // 使Z轴的零点位于X轴和Y轴所在的平面中
  plot.AppendExtra ("set ticslevel 0");

  // 设置坐标标签
  plot.AppendExtra ("set xlabel \"X Values\"");
  plot.AppendExtra ("set ylabel \"Y Values\"");
  plot.AppendExtra ("set zlabel \"Z Values\"");

  // 设置x轴和y轴的坐标范围
  plot.AppendExtra ("set xrange [-5:+5]");
  plot.AppendExtra ("set yrange [-5:+5]");

  // 初始化数据集,设置标题和风格
  // 使点通过线连接
  Gnuplot3dDataset dataset;
  dataset.SetTitle (dataTitle);
  dataset.SetStyle ("with lines");

  double x;
  double y;
  double z;

  // 创建三维数据集
  for (x = -5.0; x <= +5.0; x += 1.0)
    {
    for (y = -5.0; y <= +5.0; y += 1.0)
	{
	  // 图形曲线
	  z = x * x * y * y;

	  // 向数据集中添加坐标
	  dataset.Add (x, y, z);
	}

    // 在每一个X值数据点的末尾都需要空白线,以便3-D表面网格工作
    dataset.AddEmptyLine ();
    }

  // 把数据集添加到Gnuplot对象
  plot.AddDataset (dataset);

  // 打开plot文件
  std::ofstream plotFile (plotFileName.c_str());

  // 写plot文件
  plot.GenerateOutput (plotFile);

  // 关闭plot文件
  plotFile.close ();
}

}  // 非命名空间


int main (int argc, char *argv[])
{
  // 创建一个 2-D plot 文件.
  Create2DPlotFile();

  // 创建一个 2-D plot with error bars 文件.
  Create2DPlotWithErrorBarsFile();

  // 创建一个 3-D plot 文件.
  Create3DPlotFile();

  return 0;
}

本文参考了ns-3Manual手册https://www.nsnam.org/docs/release/3.29/manual/html/gnuplot.html?highlight=gnuplot

相关文章: