Gnuplot 科学作图 中文教程

本文原作为马欢,详情请查看科学网。如有侵权,请首页底部邮箱联系作者。

1 安装

gnuplot是一个小巧实用的数据处理工具,主要用来绘制2D/3D的数据或者函数图像,但是也包含数学计算、拟合等功能。虽然它的名字里有个“gnu”,但是它和大名鼎鼎的GNU没什么关系,使用的授权协议也不是GNU GPL,所以这里的“gnu”是小写,全名应该读作“new plot”。

所有的主流Linux发行版都包含gnuplot,因此在Linux上安装很简单,只要用各相应发行版的软件安装工具直接安装就可以了。在苹果电脑上的安装也不复杂。MacPorts项目把很多Linux上的应用程序移植到了苹果系统上,其中就包括gnuplot。只需要在苹果电脑上安装MacPorts,之后就能通过port命令安装包括gnuplot在内的各种Linux应用程序了。

在Windows下,可以直接到gnuplot在sourceforge的下载网页下载最新版本(文件名包含win32的那个),解压之后到binary目录里找到gnuplot.exe直接执行就可以了。

2 启动

gnuplot是基于命令行的交互式绘图软件。打开一个终端,输入gnuplot,随着程序启动,会出现下面的信息:(如果是在Windows电脑上,双击gnuplot.exe后会自动打开一个命令行窗口)

1695823914711

这里包含gnuplot的版本、系统、版权等信息。最关键的是最后一条:

Terminal type set to 'wxt'

什么是terminal?在gnuplot中,terminal就是说你打算用什么方式输出图片。这里默认的terminal是wxt,也就是直接输出到电脑屏幕上。gnuplot支持七十多种terminal,没必要都记住。我们以后会挑主要的几种讲一下。 提示信息之后,是gnuplot的提示符:

gnuplot>

在提示符之后输入各种命令,就可以开始画图了。

如果要退出程序,只需要输入quit或者exit命令。

3 数学表达式

在我们开始画图之前,需要知道gnuplot里面是如何表达数学公式的。

  • 加、减、乘、除、乘方

分别用+, -, *, /, **表示
 整数和浮点数
和C语言类似,gnuplot对整数和浮点数(实数)区别对待,整数的运算结果还是整数。所
以在处理整数除法时要尤其小心,例如7/2的结果是 3 而不是3.
 复数
gnuplot支持复数运算,复数用包含在花括号内的一对实数表示,例如{3,5}表示3 + 5i
 数学函数
gnuplot含有丰富的数学函数,格式和C语言几乎相同。对于实数和复数,函数名是一样的。
下面的链接可以看到预定义的函数列表:
http://www.gnuplot.info/docs_4.2/gnuplot.html#x1-5300013.
 自定义函数
自定义函数很容易,例如f(x)=x+1定义一个一元函数,f(x,y)=x+y定义一个二元函数。
 (圆周率)
在gnuplot里用pi表示。

这里是一些例子:

这里用到了print命令,就是把结果输出到屏幕上。 有了这些知识做准备,我们就可以正式开始画图了。

4 简单函数绘图

终于可以开始画图了!先从简单的函数图像入手吧。

gnuplot里面的2D作图命令是plot。先试着画一个正弦函数:
gnuplot> plot sin(5x)

这个正弦函数看着有点别扭,是吧?这是因为gnuplot默认的函数取样为 100 个点,对于快速 振荡的函数,这个取样率有点低。函数取样数目由samples这个参数控制。在gnuplot里面,所有 参数赋值都由set命令完成。我们把函数取样数目改为 500 :

gnuplot> set samples 500
gnuplot> replot

怎么样,现在看起来好多了吧?这里用到了replot命令。顾名思义,replot就是把刚才的plot 命令重新执行一遍。 图像右上角的图例(就是那个sin(5*x)后面带一段横线)看起来有点碍眼。在gnuplot里面, 这个图例叫做key。对于同时包含多组数据的图像来说,图例是必要的。但是现在图像只包含一个 函数,而且这个图例的位置也不那么对劲儿,我们先把它去掉:

gnuplot> unset key
gnuplot> replot

这里我们看到,可以用unset命令取消一个参数设置。 现在碍眼的图例没有了,但是随之而来的问题是,我们不知道这个图像究竟表示什么意思。为 了让它成为一个完整的科学作图,我们给它加上标题和坐标轴标签:

gnuplot> set title " sin (5x) ␣函数图像"
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> replot

xlabel和ylabel分别表示横轴和纵轴的标签。在gnuplot里,很多跟坐标有关的参数,都有相 应的x和y版本。title虽然可以给图像加上标题,但是在真正的科学论文里意义不大,因为所有论 文插图都要求配有文字说明(Caption)。引号内的内容为字符串,大多数情况下双引号和单引号 没有区别,除非遇到特殊字符(例如换行符nn),这时候单引号会把特殊字符当成一般字符处理, 而双引号会按照特殊字符的意义将其展开。 这里我们注意到,字符串里也可以包含中文。究竟是否支持中文,和terminal的种类有关系。 有些terminal对Unicode支持不那么好,这时候显示中文就不那么容易了。好在我们可以选择那 些比较有利的terminal。 现在我们有了一个简单的函数图像了。虽然看起来还不尽人意,但是没关系,我们以后会把它 逐渐完善。

5 坐标取值范围及刻度

我们从上一讲结束时的图像开始。

这里默认的x取值范围是从-10到 10 。我们现在希望x的取值范围从-2到 2 ,这样函数图 像可以正好包括十个周期。横坐标取值范围由xrange参数控制。还记得gnuplot里面所有参数都 由set命令控制吗?取值范围由方括号内的一对数表示,两个数之间用冒号隔开:

gnuplot> set xrange [ 2 pi :2pi ]
gnuplot> replot

(不要忘记,每一个和x坐标有关的参数,都对应有一个和y有关的参数,所以纵坐标的取值范围 由yrange控制。) 现在横坐标取值范围已经符合我们的要求了,但是横轴上的刻度并不是我们想要的。我们不想 要刻度出现在整数位置上,而是希望刻度为 的整倍数。另外,我们还希望两个主刻度之间= 2 的位置有一个分刻度,分刻度只要有刻度就可以,没必要标出数字了。gnuplot里面,横轴主刻度 和分刻度,分别用xtics和mxtics表示(m表示minor)。我们试试下面的命令:

gnuplot> set xtics pi
gnuplot> set mxtics 2
gnuplot> replot
这里的命令表示:横轴主刻度间隔为,每两个主刻度之间被分刻度分为 2 份。这组命令得到的图
像如下:

现在刻度间隔对了,但是显示的数字并不是我们想要的。我们希望显示字符,而不是小数

3.14159。其实,set xtics命令的形式并不是唯一的。我们试试下面的形式: gnuplot> set xtics ( “ 2 ” 2 pi , “” 1.5pi 1 , “” pi ,\

“” 0.5pi 1 , “0” 0 , “” 0.5pi 1 , “” pi , “” 1.5pi 1 , “2” 2pi ) gnuplot> replot 这里set xtics命令直接规定了每个刻度的位置和显示的字符。每一个刻度对应三个参数:显示字 符、刻度位置、刻度等级。刻度等级为 0 时表示主刻度,等级为 1 时表示分刻度。对于主刻度 (等级为 0 时),表示等级的参数也可以省略不写。各个刻度的参数之间用逗号隔开。从上面的例 子我们还看出,显示字符可以为空,也就是只标刻度,不显示字符。另外,如果命令太长,需要把 一条命令分为多行来写,可以在换行时末尾加上反斜杠(n),表示这条命令还没有结束。这组命 令得到的图像如下:

现在横轴坐标已经完全符合我们要求了,我们把纵轴坐标也调整一下,因为我们不需要这么细

的划分纵轴刻度:

gnuplot> set ytics 1 ,0.5 ,
gnuplot> replot

这里又用了set ytics命令的另一种形式(再次提醒一下,xtics和ytics语法是完全一样的):后面 跟了逗号隔开的三个参数。这三个参数分别表示:最小主刻度、主刻度步长、最大主刻度。图像如 下:

现在我们完成了对于坐标轴的一些微调,图像看起来更顺眼了。

6 简单数据绘图

之前讲过了简单的函数绘图,而实际科研中更多用到的是数据绘图。

在讲如何用gnuplot进行数据绘图之前,我们先介绍一个gnuplot里最有用的命令:help。
gnuplot内含一个非常有用的帮助系统。随着我们学习的命令越来越多,记住所有命令的用法
不太现实,所以我们会更多的依赖这个帮助系统。例如,我们想知道set xtics命令的用法,只要在
gnuplot里输入:
gnuplot>help set xtics
就能得到完整的set xtics用法及实例。
好了,下面我们讲数据绘图。首先介绍我们的数据文件。这是一个关于北京市一年中每月平均
降水量的数据,我们的数据以纯文本方式储存在文件名为datafile.dat的文件中,文件全文如下:

文件开始

北京月平均降水量(mm)
月份 降水量
==============
1 2.
2 5.
3 10.
4 25.
5 27.
6 71.
7 175.
8 182.
9 48.
10 17.
11 5.
12 2.

文件结束

数据分为两列,第一列为月份,第二列为降水量。以#符号开始的各行为注释,也就是说,
这些行对绘图不构成任何影响。下面开始画图。
gnuplot> set xlabel "月份"
gnuplot> set ylabel "降水量(毫米)"
gnuplot> set title "北京市月平均降水量"
gnuplot> unset key
gnuplot> set xrange [ 0. 5 : 1 2. 5 ]
gnuplot> set xtics 1 ,1 ,
gnuplot> plot " d a t a f i l e. dat"

这里我们看到,默认的数据作图是画出各数据点。如果我们希望得到数据连线呢?可以使用下面的命令:

gnuplot> plot " d a t a f i l e. dat" with l i n e s

with命令后面跟的是画图方式,这里使用的是lines方式,也就是把各个数据用直线连接起 来。gnuplot大约支持三十种画图方式,默认为points方式,我们以后会选择一些常用的方式来介 绍。 现在问题来了:如何既得到连线,又得到数据点呢?对了,用with linespoints: gnuplot> plot “ d a t a f i l e. dat” with l i n e s p o i n t s

好了,我们已经有一个简单的数据图了。下次我们想办法让它看起来更漂亮一些。

7 点线风格

我们接着上次的数据图谈起。上次我们得到了一个“点线”图,它的数据点是由小“+”字表示的,但是似乎太小了,有点看不清楚。另外,如果我们想在做报告时把这个图用到幻灯片中去,

小“+”字很不醒目,这时候我们可能想用其他的标志。gnuplot里面有几个控制点和线画法风格的参
数:
linestyle连线风格(包括linetype,linewidth等)
linetype连线种类
linewidth连线粗细
linecolor 连线颜色
pointtype 点的种类
pointsize点的大小

我们看下面的例子: gnuplot> plot “ d a t a f i l e. dat” with l i n e s p o i n t s l i n e c o l o r 3 linewidth 2\

pointtype 7 pointsize 2

这几个参数的用法不难理解,直接跟在with命令之后就可以了,但是 2 、 3 、 7 这些数字都代表 什么意思呢?这些数字是代表不同画法风格的代码,具体某个数字代表什么意思,这个依赖于我们 使用的terminal(还记得我们在第二讲里曾经讲过的terminal吗?)拿我们现在正在使用的wxt terminal举例,如果想知道这些数字究竟代表什么意思,可以输入命令:

gnuplot> test

这样当前terminal会输出一个测试图:

测试图中包含当前terminal的风格代码实例。例如,左下角显示的是连线粗细,右边显示的是 色彩和数据点显示风格对应代码。 最后,告诉大家一个好消息:gnuplot里面很多命令有缩写形式。例如上面例子中的绘图命令 可以简写为:

gnuplot> plot " d a t a f i l e. dat" w lp l c 3 lw 2 pt 7 ps 2

至于其他参数命令的缩写形式,相信不难猜出来,大家可以试验一下猜猜看。

8 多组数据绘图

之前讲了如何用gnuplot进行数据绘图。实验中经常碰到的情况是,我们要同时处理多组数
据。这一次我们来讲一讲,怎样把多组数据绘制到同一个图上。
还拿城市降水量举例,下面是我们的数据文件,文件名是“precipitation.dat”:

文件开始

各城市月平均降水量 (mm)
月份 北京 上海
======================
1 2.5 38.
2 5.1 58.
3 10.2 81.
4 25.4 101.
5 27.9 114.
6 71.1 152.
7 175.3 129.
8 182.9 132.
9 48.3 154.
10 17.8 61.
11 5.1 50.
12 2.5 35.

文件结束

我们在 gnuplot里面执行下面的命令:

gnuplot> set xlabel "月份"
gnuplot> set ylabel "降水量(毫米)"
gnuplot> set title "各城市月平均降水量"
gnuplot> set xrange [ 0. 5 : 1 2. 5 ]
gnuplot> set xtics 1 ,1 ,
gnuplot> plot " p r e c i p i t a t i o n. dat" using 1:2 w lp pt 5 ,\" p r e c i p i t a t i o n. dat" using 1:3 w lp pt 7

这里我们用了一个新的命令:using。在我们的数据文件包含超过一组数据时,我们可以用 using指定使用哪列数据。例如using 1:2表示使用第一列和第二列数据,第一列为横轴,第二列为 纵轴。以此类推,using 1:3表示使用第一列和第三列数据。如果想把多组数据绘制到一个图上,只 要使用一个plot命令,后面跟多组数据,每组数据之间用逗号隔开就可以了。 显然,这里的图例又把图像搞乱了。我们没有像以前那样把图例去掉,因为这里有两组数据, 我们需要保留图例。怎么办呢?我们来使用下面的命令:

gnuplot> plot " p r e c i p i t a t i o n. dat" u 1:2 w lp pt 5 title "北京" ,\" p r e c i p i t a t i o n. dat" u 1:3 w lp pt 7 title "上海"
注意到了吗?这里我们使用了字母u作为using的缩写。另外,这里用了新的参数title。这里
的title和之前我们用过的set title不同。set title指定的是整个图的标题,而这里的title跟在每一
组数据参数后面,指定的是每组数据对应的图例中的title。这样,我们的图看起来整洁多了。

using命令除了指定所用的数据列,还可以对数据进行运算操作。例如,我们现在还是绘制上 面的数据,但是降水量单位使用英寸而不是毫米。我们知道, 1 英寸=25.4毫米,所以我们执行下面 的命令:

gnuplot> set ylabel "降水量(英寸)"
gnuplot> plot " p r e c i p i t a t i o n. dat" u 1 : ( $2 /25.4) w lp pt 5 title "北京" ,\" p r e c i p i t a t i o n. dat" u 1 : ( $3 /25.4) w lp pt 7 title "上海"

在对特定列的数据进行运算操作时,我们需要在列号之前加上$符号,这样表示该数据的值。虽然这里的例子是同一个文件里的多组数据,但是如果数据存在多个文件里,这里的命令同样适用。

9 输出 eps图片

到目前为止,我们所有的gnuplot作图都只是输出到电脑屏幕上。如果要在我们的文档里使用
这些图片,我们必须把它们以某种文件格式存储下来。前面已经介绍过,gnuplot里面控制图像输
出方式的命令是terminal。我们这次就讲一下如何把图片输出为eps文件。
之所以首先选择eps,是因为大量科学技术文档使用LATEX来编辑排版,而eps是LATEX最常
用的图片格式,支持高质量的矢量图形,并且可以方便的转换为pdf、svg等其他常用格式。
首先,让我们看看如何设置terminal。在gnuplot里输入下面的命令:
gnuplot> set terminal p o s t s c r i p t eps
这里的terminal其实是postscript,而eps是作为postscript的一个参数。这并不奇怪,因为eps
本来就是postscript衍生出来的。输入这个命令之后,gnuplot会自动返回下面的信息:

这里给出了一些默认的其它参数。gnuplot下的每一个terminal所带的参数不完全相同,一些 参数只针对某一terminal。我们只需要知道一些常用terminal的常用参数,而其它的terminal和参 数,我们可以在使用的时候通过help命令查询。现在我们暂且不管这些参数,先画一个图试试。 还是用我们上次用过的降水量数据文件: gnuplot> set xlabel “Month” gnuplot> set ylabel “ P r e c i p i t a t i o n ␣ (mm) “ gnuplot> set xrange [ 0. 5 : 1 2. 5 ] gnuplot> set xtics 1 ,1 , gnuplot> set output “ p r e c i p i t a t i o n. eps “ gnuplot> plot “ p r e c i p i t a t i o n. dat” using 1:2 w lp pt 5 title “ Beijing “ ,\

“ p r e c i p i t a t i o n. dat” using 1:3 w lp pt 7 title “Shanghai” gnuplot> set output gnuplot> set term wxt 这里我们没有使用中文标签,因为在postscript使用中文字体并不容易。以后我们会介绍如何 绕过这个障碍。 第五行有一个新命令:set output。这没什么多说的,就是指定输出文件的文件名。第七行还 有一个set output,但是后面没有跟任何文件名。这其实是告诉gnuplot,这个文件已经输出完毕, 可以关闭了。另外也可以用unset output,其实是相同作用。之所以这么做,是因为有些terminal 支持多页文件,所以在画完图之后,gnuplot并不自动关闭文件,等待你输入下一页内容,除非你 手动关闭,切换terminal,或者退出gnuplot程序。 最后,别忘了把terminal切换回屏幕显示,这样可以避免一些意想不到的事情发生。注意:我 们又用缩写了! 下面让我们来看看生成的eps文件吧:

0
20
40
60
80
100
120
140
160
180
200
1 2 3 4 5 6 7 8 9 10 11 12
Precipitation (mm)
Month
ShanghaiBeijing

这个图像可能并不是我们想要的。有几个地方我们想要修改一下:

 这个图是黑白的!我们想要彩色图。

 有一组连线是虚线。这也难怪,黑白图如果不用虚线,还真分辨不出来。但我们想要彩色实线。

 让直线稍微加粗一点。

 标签文字显得小了些,我们想要大一点的字体。

我们来重新画一下这个图:

gnuplot> set terminal p o s t s c r i p t eps color s o l i d linewidth 2 " Helvetica " 20
gnuplot> set output " pr eci pi ta tio ncolor. eps "
gnuplot> replot
gnuplot> set output
gnuplot> set term wxt

这里我们用color参数表示我们要彩色图,solid表示我们要实线不要虚线,linewidth参数指定 2 倍线宽,而最后指定使用Helvetica 20号字体。让我们来看看新生成的eps文件:

0
20
40
60
80
100
120
140
160
180
200
1 2 3 4 5 6 7 8 9 10 11 12
Precipitation (mm)
Month
Beijing
Shanghai
这里的字体为postscript level 2 字体,共有 35 种。除了Helvetica,常用的还有 Times-
Roman。如果硬要多记两个字体名字,就记住Courier和Symbol吧。Courier是编程时常用的等宽
字体,而Symbol字体可以用来显示希腊字母。如果你实在好奇还有哪些其它字体,可以看看下面
的网页链接:http://xfig.org/userman/attributes.html#font-panel

10 输出 pdf和png 图片

这次讲讲怎样把图片输出为pdf和png格式。 上次讲过的eps文件其实很容易转换为pdf,为什么我们还专门讲一下pdf格式输出呢?因为 在postscript terminal下很难使用中文字体,而在pdf下面就容易多了,而pdf文件又很容易转换 回eps,这样就绕开了eps中文支持不好的问题。 png是一种无损压缩位图格式,图形质量优于jpg等有损压缩格式,支持透明效果,可以生成 非常小体积的文件,适于放在网上交流。通过各种图像处理软件,png文件也很容易转换为其他位 图格式。 下面首先看一个pdf输出的例子,咱们还是用之前用过的城市降水量数据文件: gnuplot> set xlabel “月份” gnuplot> set ylabel “降水量(毫米)” gnuplot> set title “各城市月平均降水量” gnuplot> set xrange [ 0. 5 : 1 2. 5 ] gnuplot> set xtics 1 ,1 ,12 gnuplot> set term pdfcairo lw 2 font “Times␣New␣Roman,8 “ gnuplot> set output “ p r e c i p i t a t i o n. pdf” gnuplot> plot “ p r e c i p i t a t i o n. dat” u 1:2 w lp pt 5 title “北京” ,\

“ p r e c i p i t a t i o n. dat” u 1:3 w lp pt 7 title “上海” gnuplot> set output 这里我们用的terminal是pdfcairo,而不是简单的pdf。区别是pdfcairo使用了cairo(一个2D图 形程序库)和pango(一个字体渲染程序库)来生成pdf文件,优点是更好的国际支持。有了之前 的经验,这里的terminal参数不需要多解释了。这里我们使用了“Times New Roman” 8号字体。

和eps下使用postscript字体不同,这里可以是电脑系统里安装的任何字体。在Linux下,可以使 用fc-list命令察看系统里到底有哪些字体可用。 下面我们来看生成的pdf图片:












       
  
   










这里有一个小问题:虽然数字使用了Times New Roman字体,但是汉字使用了其他字体(这 里是我的系统默认的“文泉驿正黑”)。这是因为Times New Roman本来就不是中文字体。如果我 们想让中英文混排时字体统一,必须使用支持中文的字体。 下面我们来看png输出的例子: gnuplot> set term pngcairo lw 2 font “AR␣PL␣UKai␣CN,14 “ gnuplot> set output “ p r e c i p i t a t i o n. png” gnuplot> replot gnuplot> set output gnuplot> set term wxt

基于和上面同样的原因,这里使用的terminal是pngcairo而不是简单的png,而字体是AR PL UKai CN(文鼎简中楷)。下面是生成的png图片:

11 Enhanced文本模式

我们之前的图像里的title、xlabel等标签里用到的都是纯文本字符串,如果我们希望输出稍复 杂一点的文字标签,例如字母加角标,我们可以使用enhanced文本模式。 gnuplot里面好多terminal都支持enhanced模式,使用方法就是在set terminal的时候,在后 面加上enhanced参数。enhanced模式里有一些表达特殊含义的字符,利用这些字符可以构成一些 比较复杂的文字输出。这些特殊字符主要包括:

  1. ˆ:表示后面的字符为上角标

  2. _:表示后面的字符为下角标

  3. @:表示后面的字符不占任何宽度

  4. &{”string”}:表示一段空白,空白的长度等于花括号内那段字符串所占宽度

  5. ̃:表示后面的两个字符重叠打印(相当于打字机在同一位置打印两个字符);也可以在第二 个字符前加上一个数字,表示第二个字符相对于第一个字符有一个竖直方向的移动,移动距 离等于该数字乘以字符尺寸。

上面提到的“字符”,也可以是包含在花括号({})内的“字符串”。除了上面这些特殊标志,还可以 临时改变字符(或字符串)的字体,方法是:

{/字体名=字体大小 字符}

下面我们看一些例子:

 "a^x"
 "a_x"

 “a^b_{cd}”

这里的上下角标没有对齐,因为上标b需要占一定宽度

 “a^@b_{cd}”

这里我们看到了@的作用

 “abc&{de}fg”

这里&后面的字符没有显示,留出一段和这些字符同样宽度的空白

 “~a{1.2\_}”

注意这里的两个反斜杠。因为下横杠(_)是一个特殊字符,需要在前面加反斜杠n来表示
它本来的意义,而反斜杠本身也是一个特殊字符,需要在它前面再加一个反斜杠。我们在第
四讲里谈到过双引号和单引号的区别。如果我们在这里用单引号而不是双引号,那么只需要
一个反斜杠就可以了。这里的1.2表示后面的字符(_)向上移动1.2个字符大小的距离。

 {/Symbol abc}abc

这里第一个花括号里的abc使用了Symbol字体,而后面括号外的abc使用的是默认字体。
注意字体名称前的斜杠方向。这里我们看到,Symbol字体里的英文字母对应显示的是希腊字
母。Symbol字体里还包括了一些其它符号,下面是完整的Symbol字体列表:

上面图中显示的是Symbol字体对应的 16 进制代码。例如上面例子中的希腊字母

,对应的 16 进 制代码分别为 61 、 62 、 63 ,转换为 8 进制代码就是 141 、 142 、 143 。在gnuplot里,我们可以直接 用字符的 8 进制代码表示这个字符,所以我们也可以用{/Symbol \141\142\143}来表示

。 根据上面的内容,下面是一个综合起来的例子: gnuplot> set term wxt enhanced gnuplot> set xlabel “X” gnuplot> set ylabel “Y” gnuplot> set xrange [ 0 : 1 0 ] gnuplot> set xtics 0 ,1 ,10 gnuplot> unset key gnuplot> set title “ f (x) ␣=␣{/Symbol=16␣\326}~{x^@3}{1.1{/ Symbol=16␣\276}}&{aa}\

␣函数图像” gnuplot> plot sqrt(x3)

虽然利用enhanced模式也能显示一些简单的数学表达式,但是对于稍微复杂一点的公式来 说,显示效果无法令人满意。要在gnuplot里显示数学公式,终极方案还是要用LATEX。

12 插入 LATEX公式

上一次我们谈过,在gnuplot里使用enhanced模式虽然可以生成一些简单的数学表达式,但 是对于稍复杂的数学公式来说,enhanced模式没办法生成令人满意的结果。这里我们介绍gnuplot 的另外一个terminal:epslatex。 epslatex和我们之前介绍过的postscript eps输出方式非常接近,因此它们很多参数都是相同 的。区别在于,epslatex使用postscript eps仅生成图形存于eps文件,而所有文字标签包含在另外 一个LATEX文件中。在gnuplot完成输出之后,使用LATEX命令最终生成完整的图片。这种做法的 好处是不言而喻的,即使在输出完成后,我们仍然可以编辑LATEX文件获得我们想要的显示效果。 下面我们看例子: gnuplot> set xlabel ’X’ gnuplot> set ylabel ’Y’ gnuplot> set title ’ Error ␣ function ␣$\ d i s p l a y s t y l e \mathrm{ e r f }(x) ␣=␣\ f r a c {2}{ sqrt {\ pi }}␣\int_0^x␣e^{t ^2}\ ,\mathrm{d} t$ ’ gnuplot> set xrange [4:4] gnuplot> set yrange [1. 1 : 1. 1 ] gnuplot> unset key gnuplot> set term epslatex standalone lw 2 color 11 gnuplot> set output “ e r f. tex “ gnuplot> plot erf(x) lw 2 gnuplot> set output

前三行的标签文字,我们使用了单引号,避免了双引号内需要连着两个反斜杠的麻烦。在title里 面,我们使用了LATEX数学公式。在set term命令里,standalone是一个新的参数,它表示生成完 整的LATEX文件。如果没有这个参数,生成的LATEX文件将不能单独编译,必须把代码插入其它的 LATEX文件中编译。set term最后的数字 11 代表字体大小。set output只需指定LATEX文件名,而

不需要指定eps文件名。我们谈到过gnuplot包含很多预定义的函数,这里的erf就是其中之一, 表示误差函数。 我们通过epstopdf命令将生成的eps图片转为pdf,然后用pdflatex命令可以把图片直接编译 为pdf文件,下面是显示的效果:

-1
-0.5
0
0.5
1
-4 -3 -2 -1 0 1 2 3 4
Y
X
Errorfunctionerf(x) =√^2 π
∫x
0
e−t^2 dt

怎么样?LATEX的数学公式效果真不是盖的。

13 栅格以及方程数值解估算

我们现在来画一个 0 阶贝塞尔函数J 0 (x):
gnuplot> set term wxt enhanced
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set xrange [ 0 : 1 0 ]
gnuplot> set xtics 0 ,1 ,10
gnuplot> unset key
gnuplot> set title "0阶贝塞尔函数 J_0(x) "
gnuplot> plot besj0(x)

这里的besj0(x)就是gnuplot里面预定义的 0 阶贝塞尔函数。如果现在请您从这个图上估计出 [0, 10]内J 0 (x)的零点数值,也就是方程J 0 (x) = 0的解,恐怕您很难说的准确。但是如果为这个 图加上栅格(grid),就容易多了:

gnuplot> set grid gnuplot> replot 这时我们很容易估计出三个零点的数值:2.4, 5.5, 8.6。通过查表我们可以知道,这三个零点比 较精确的数值分别为2.4048, 5.5201, 8.6537。这和我们的估计值差不太多。如果我们想更精确的估 计数值,可以尝试改一下xrange:

gnuplot> set xrange [ 8 : 9 ] gnuplot> set xtics 8 ,0.1 ,9 gnuplot> replot 这相当于把图像在零点附近放大了。把鼠标放在画图区域,画图框左下角就会显示出鼠标所在 位置的坐标。现在我们把鼠标放在函数图线和X轴的交叉点上,左下角显示的横坐标为8.65243, 这和我们查表所得的数值更接近了。 如果想进一步让结果精确一些,我们可以利用gnuplot的计算功能。我们可以通过尝试计算的 方法获得方程的数值解:

gnuplot> print besj0(8 .65)
0.00101216621937318
gnuplot> print besj0(8 .66)
0.0017019446057587
gnuplot> print besj0(8.6537)
7.5770361108123 e 06
gnuplot> print besj0(8.6536)
3.47225104115535 e 05
gnuplot> print besj0(8.6538)
1.95681245811775e 05
所以在8.6附近,J 0 (x) = 0精确到小数点后 4 位的数值解为 8.6537,这和我们查表的结果一
模一样。由于我们已经通过图像知道了数值解的大概位置,再加上合理利用线性插值,我们可以很
快得到精确的结果。

14 第二坐标轴

回首看看我们以前所有的作图,横坐标都标示在底部,而纵坐标都标示在左侧。其实,在图像顶部和右侧,还隐藏着一对不太引人注意的坐标轴,我们可以管它们叫做“第二坐标轴”。平时,它们只是第一对坐标轴的镜像;在我们需要的时候,它们可以用来表示不同的物理量。有时候,我们会有两组性质不同但是又相互关联的数据,这时候我们或许想把他们画在同一副图上,以便比较。还拿北京市月平均降水量举例,但是这次,我们把温度也加上。下面是我们的数据文件

weather_beijing.dat:
### 文件开始 ###
#北京月平均降水量(毫米)及气温(摄氏度)
#
#月份 降水量 气温
# ===================
1 2.5 -4
2 5.1 -2
3 10.2 6
4 25.4 13
5 27.9 20
6 71.1 24
7 175.3 26
8 182.9 25
9 48.3 20
10 17.8 13
11 5.1 5
12 2.5 -2
### 文件结束 ###

我们之前讲过的所有有关坐标的参数,在第二坐标轴上均适用,只不过相应的名字起始字母 改为x2或者y2,例如ylabel改为y2label。另外,plot命令有一个新的参数axis,用来控制使用 哪个坐标轴,例如axis x1y2就表示使用第一横轴和第二纵轴。现在我们来看用上面数据作图的例 子: gnuplot> set xlabel “月份” gnuplot> set ylabel “降水量(毫米)” gnuplot> set y2label “气温(摄氏度)” gnuplot> set title “北京市月平均降水量及气温” gnuplot> set xrange [ 0. 5 : 1 2. 5 ] gnuplot> set xtics 1 ,1 ,12 gnuplot> plot “ weather_beijing. dat” u 1:2 w lp pt 5 l c rgbcolor “#2B60DE”\

axis x1y1 t “降水量” , “ weather_beijing. dat” u 1:3 w lp pt 7 l c rgbcolor “#F62817” axis x1y2 t “气温”

这里的气温数据使用了图像右边的第二纵轴y2,但是y2轴上的刻度并没有变化,依然是左边 y1轴的镜像。我们在这里有两件事要做:

  1. 去除右边纵轴上的y1刻度镜像,否则这些刻度标记将和新的y2刻度标记混起来,导致无法 识别;

  2. 在右边纵轴上加上y2刻度标记。

我们执行下面的命令:

gnuplot> set ytics nomirror
gnuplot> set y 2 t i c s
gnuplot> replot

好了,现在降水量和温度数据分别对应于左侧和右侧的纵坐标。

看到这里,我们可能有点怀念我们上一讲谈到的grid。如果能加上栅格,数据图示就更清楚 了。但是现在我们有两组不同的纵坐标,如果都开启栅格,还不乱套了?set grid命令允许我们在 开启栅格时,选择使用哪一组坐标。例如:

gnuplot> set grid xtics y 2 t i c s

会开启x1和y2的栅格。但是这还是不能兼顾两组数据。最好的解决方案是,让两个纵轴有相同数 目的分格,这样两套grid也就重合了,开启任何一个就可以了。例如,上面的图中左侧纵轴有 10 个分格,我们让右侧纵轴也有 10 个分格:

gnuplot> set y2range [10:40]
gnuplot> set y 2 t i c s 5
gnuplot> set grid
gnuplot> replot

现在看起来好多了。

最后,不知道大家注意到没有,在开始的plot命令里,我们用了新的方式定义图线颜色。在第 七讲“点线风格”里,我们提到过,可以用预定义的数字代码来定义图线颜色。但是在这里,我们使 用了rgbcolor来定义颜色,这很大程度上增加了颜色选择范围,允许更好的显示效果。而其用法也 很简单,就是在rgbcolor之后,加上颜色的RGB代码,了解HTML的朋友应该对这个不陌生。

15 Gnuplot的坐标系统及标签

我们现在知道了gnuplot有第一(first)和第二(second)两套坐标系统,但是gnuplot的坐标 系统还不止于此。除此之外,它还有graph,screen和character三套坐标系统。 graph和screen都是归一化的坐标系统。graph以坐标轴包围区域为界,左下角为0,0,右上 角为1,1;screen以整个图片区域为界,左下角为0,0,右上角为1,1。 character顾名思义,是以字符大小为单位长度的坐标系统,因此它的单位长度依赖于字体大 小。它的原点位置和screen相同。 下面我们结合label命令来了解一下这几个坐标系统。我们之前讲过xlabel和ylabel。而这里 的label命令,是在图中任何地方插入文字标签。还是来看例子:

gnuplot> sinc (x) = sin( pix) /( pix)
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> unset key
gnuplot> set samples 500
gnuplot> set xrange [5:5]
gnuplot> set xtics 1
gnuplot> set x2range [ 0 : 1 0 ]
gnuplot> set x 2 t i c s 1
gnuplot> set y2range [2:5]
gnuplot> set y 2 t i c s 1
gnuplot> set grid
gnuplot> set label 1 " Hello ␣ f i r s t " at 2 ,0.5
gnuplot> set label 2 " Hello ␣ second " at second 2 ,0.5
gnuplot> set label 3 " Hello ␣graph" at graph 0. 2 , 0. 5
gnuplot> set label 4 " Hello ␣ screen " at screen 0. 2 , 0. 5
gnuplot> set label 5 " Hello ␣ character " at character 10 ,5
gnuplot> plot sinc (x)

这里我们画一个sinc函数图像。为了说明问题,我们把第二坐标系也都标示了出来,虽然函数图像 并没有用到第二坐标。其他命令前面都讲过了,这里只看五个set label命令。set label之后紧跟的 那个整数,就是一个标识符,用以区别各个label,可以随便选个整数。在字符串之后,at参数指 定标签坐标。默认为first坐标系统,也可以使用其它坐标系统。下面是生成的图片:

为了帮助大家理解,我们把graph和screen各自的坐标区域分别用绿色和橙色表示了出来。 标签文字的默认对齐方式为居左,也就是指定的坐标位置在文字的左边。我们也可以在label 命令里选择其他对齐方式。除此之外,我们还可以在label命令里指定文字颜色,旋转文字,或者 在指定坐标位置处加一个点。下面例子中的每个参数不必一一解释了,因为和我们前面接触过的命 令都是一致的:

gnuplot> set label 1 " Hello ␣ red ␣ l e f t " at 2 ,0.4 l e f t t e x t c o l o r rgb "#FF0000"
gnuplot> set label 2 " Hello ␣ green ␣ center " at 2 ,0.5 center t e x t c o l o r rgb "#00
FF00"
gnuplot> set label 3 " Hello ␣ blue ␣ right " at 2 ,0.6 right t e x t c o l o r rgb "#0000FF"
gnuplot> set label 4 " Hello ␣ rotate " at 2 ,0.4 rotate by 45
gnuplot> set label 5 " Hello ␣ point " at 3 ,0.2 point pt 7 l c rgb "#FF9900"
gnuplot> replot

16 箭头

有了坐标系的知识打底,其他很多东西很好谈了。我们的图上除了标签之外,还有一个常用的

标志:箭头。关于箭头的命令是set arrow,语法和label有些类似,包括以下这些常用参数:

 from ... to ...
箭头的起点和终点坐标。如果把to换成rto,第二个坐标就表示相对位置而不是绝对坐标。
 nohead, head, backhead, heads
分别表示:没有箭头(其实就是线段),箭头在终点,箭头在起点,双向都有箭头。
 size <length>,<angle>,<backangle>
箭头尺寸,默认长度单位为first坐标单位长度。
下图中A,B,C分别代表<length>,<angle>,<backangle>。
C B
A
 filled, empty, nofilled
箭头的三种填充风格:
Filled
Empty
Nofilled

下面我们看例子,还是画sinc(x)函数:

gnuplot> set term wxt font "DejaVu␣Sans ,12 "
gnuplot> sinc (x) = sin( pix) /( pix)
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set yrange [0. 4 : 1. 2 ]
gnuplot> set title " sinc (x) ␣函数"
gnuplot> unset key
gnuplot> set samples 500
gnuplot> set arrow 1 from 2 ,1.05 to 0.3 ,1 f i l l e d size 0.5 ,15 ,60 lw 2
gnuplot> set label 1 at 0 ,1 point pt 7 ps 1.5 l c rgb "#F87217"
gnuplot> set label 2 "最大值在(0, 1)" at 2.1 ,1.05
gnuplot> plot sinc (x) lw 2

17 边框和坐标轴

我们现在所有绘图的坐标刻度均标在图像边框上,无论上下左右。这样做的好处是函数或数据图线清楚,不会和坐标标注混在一起。其实,我们小时候数学课上最早学习坐标系的时候,都是让X轴和Y轴正交于原点,而刻度标注在坐标轴上。这样的图像在定性表现函数关系,尤其有一定对称性的函数关系时,比较一目了然。

让我们来看看怎样用gnuplot得到这样的效果。
  1. 用unset border命令把边框去掉;

  2. 用set zeroaxis命令画出正交于原点的坐标轴;

  3. 在设定坐标刻度时加上axis参数,这样刻度会出现在坐标轴上面,而不是边框上。

为了避免审美疲劳,这次我们拿高斯函数举个例子:

gnuplot> set term wxt enhanced font "Times␣New␣Roman,16 "
gnuplot> gauss (x) = exp(pixx)
gnuplot> set title "函数 e^{x^2}"
gnuplot> set samples 500
gnuplot> set xrange [3:3]
gnuplot> set yrange [0. 2 : 1. 2 ]
gnuplot> unset key
gnuplot> unset border
gnuplot> set zeroaxis l t 1 lw 2
gnuplot> set xtics axis 2 ,1 ,2
gnuplot> set ytics axis 0 ,1 ,1
gnuplot> plot gauss (x) lw 3

例子中的参数前面都介绍过,如果不记得了,可以复习一下“坐标取值范围及刻度”和“点线风格”等章节。这里的图像已经很像模像样了,除了标签位置还不那么理想,而且坐标轴没有箭头。幸好,我们上一讲刚刚谈到过箭头,下面来试试做一下微调:

gnuplot> set title "函数 e^{x^2}" o f f s e t 12, 5
gnuplot> set xtics axis 2 ,1 ,2 o f f s e t 0.4 ,0
gnuplot> set ytics axis 0 ,1 ,1 o f f s e t 0 ,0.4
gnuplot> set arrow 1 from 2 ,0 to 3.2 ,0 f i l l e d size 0.2 ,15 ,60 lw 2
gnuplot> set arrow 2 from 0 ,1 to 0 ,1.22 f i l l e d size 0.2 ,15 ,60 lw 2
gnuplot> set rmargin 4
gnuplot> set label 1 "X" at 3.0 ,0.1
gnuplot> set label 2 "Y" at 0.3 ,1.2
gnuplot> replot

这里有几个命令同时用到了新的参数:offset。它的作用就是把命令里提到的标签文字平移一段 距离。在这里,offset默认的坐标系统是character。我们慢慢会体会到这种做法的好处,它使得我 们很多时候改变字体大小,而不必重新设置offset。 另外,set rmargin命令用于设置图像右边空白宽度,单位也是character。一般情况下,四边 空白宽度都是自动设置的。现在我们在右边增加了箭头,而绘图显示区域不会因此自动扩大,这样 会导致箭头无法完整显示,所以要手动改一下设置。相应的,上、左、下边的空白宽度,分别由 tmargin,lmargin,bmargin参数控制。

18 图例

在同一图像中包含多组数据或函数时,图例是必要的。我们这一次谈一谈图例的微调。

这次来画前 3 阶的第一类贝塞尔函数Jn(x)。在gnuplot里, 0 阶和 1 阶贝塞尔函数已经定义 了,分别为besj0(x)和besj1(x),而 2 阶贝塞尔函数可以通过递推关系构造出来。下面是例子:

gnuplot> set term wxt enhanced
gnuplot> besj2 (x) = besj1(x)2/x besj0(x)
gnuplot> set xrange [ 0 : 2 0 ]
gnuplot> set xtics 2
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set title " Bessel ␣ Functions ␣ of ␣ the ␣ First ␣Kind"
gnuplot> set grid
gnuplot> set style l i n e 1 lw 2 l c rgb "#F62217"
gnuplot> set style l i n e 2 lw 2 l c rgb "#D4A017"
gnuplot> set style l i n e 3 lw 2 l c rgb "#2B60DE"
gnuplot> plot besj0(x) l s 1 t "J_0(x) " , besj1(x) l s 2 t "J_1(x) " , besj2 (x) l s 3
t "J_2(x) "

之前我们讲过,plot命令后面可以跟随一些参数(例如linewidth, linecolor等)来改变点线风 格。在上面的例子中,我们把这些参数单独拿出来放到了set style命令里,定义了三个linestyle, 然后在plot命令里再调用这些linestyle。这样子做和我们之前的做法效果上没什么不同,唯一的区 别是让plot命令短了一些。另外,改变风格可能容易一点。 上面是默认的图例,下面让我们进行微调。

  1. 为图例加上边框

gnuplot> set key box
gnuplot> replot
  1. 改变图例显示位置

gnuplot> set key center at 10 ,0.7
gnuplot> replot
  1. 把图例的title和图线示例调换位置

gnuplot> set key reverse
gnuplot> replot
  1. 调整图例边框宽度width(或高度height)

gnuplot> set key width 1
gnuplot> replot
  1. 调整title文字对齐方式(Left或者Right,注意首字母大写) gnuplot> set key Left gnuplot> replot

  2. 调整图例行间隔

gnuplot> set key spacing 1.2
gnuplot> replot
  1. 调整图线示例长度

gnuplot> set key samplen 2
gnuplot> replot

这些并不是set key的全部参数。在gnuplot里,如果想深入了解任何命令的详细用法,不要忘记 使用help命令。

19 对数坐标

我们这次来谈谈怎样在gnuplot里面绘制对数坐标图。我们先在一般直角坐标系里画一下函数 3x的图像:

gnuplot> set term wxt enhanced
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> unset key
gnuplot> set title "函数 3^x 图像"
gnuplot> set xrange [ 0. 1 : 2 0 ]
gnuplot> plot 3 x lw 2
下面把y轴改为对数坐标:
gnuplot> set logscale y
gnuplot> replot

set logscale命令用于指定对数坐标轴,这个例子中是y轴。如果要使用双对数坐标,只需执 行:

set logscale xy 这里y轴的数字标注有点不好看,因为默认情况下gnuplot根据数字大小自动选择数字格式。 我们希望用一致的方式,例如都以指数方式显示数字。我们可以用set format命令来指定数字显示 格式,使用方法为set format加上坐标轴,再加上表示格式的字符串:

gnuplot> set format y "%.0 e"
gnuplot> replot

后面表示数字格式的字符串,对于熟悉C语言的读者应该不陌生,它和printf函数中表示数字格式 的字符串非常类似。常见的有以下几个:

 %f 小数格式
 %e 指数格式
 %g 根据长度自动选择%f或者%e
 %t 指数格式的有效数字部分
 %T 指数格式的指数部分

另外,各特殊字符之前的数字可以用于表示有效数字的精度。

20 图像尺寸

当我们在gnuplot里面执行:
gnuplot> set term pngcairo

我们会发现有如下的返回信息:

Terminal type set to ’ pngcairo ’
Options are ’ ␣ s i z e ␣ 640 , ␣480␣ ’

这表示输出的png图片默认大小是640x480像素。如果我们想改变输出图片的大小,可以在set term命令之后加上size参数,例如:

gnuplot> set term pngcairo size 800 ,600

对于eps和pdf输出,默认的size单位是英寸,而不是像素。这是因为eps和pdf均是矢量图片, 像素值没什么意义。 除了在设置terminal的时候可以指定size参数,gnuplot里面还有一个单独的set size命令。 这两种设置方法的区别在于:

 set terminal的时候size参数指定的是整个图片的尺寸,包括标签、标题、四边空白等等,而
set size命令指定的仅仅是绘图区域的尺寸;
 set terminal的时候size参数指定的是绝对尺寸,例如像素、英寸等,而set size命令指定的
是相对尺寸,也就是绘图区域相对于整个图片大小的比例。例如set size 0.5,0.5时,绘图区域
仅占整个图片大小的四分之一。

由于上述第二点,set size命令更常用的形式是set size ratio,这时只需给出绘图区域高和宽的比 例,例如:

gnuplot> set size r a t i o 0.5

将会画出高宽比为1:2的图像。而高宽比为 1 的图像(也就是正方形),还有一个单独的设置方 法:

gnuplot> set size square 在gnuplot旧的版本中,这两种设置尺寸的方法比较混乱。从gnuplot 4.4起,基本上都统一为 上述方式。

21 极坐标

gnuplot可以在极坐标下绘图,相应命令是:
gnuplot> set polar

然后会出现下面的返回信息:

dummy variable i s t f o r curves

这表明,在极坐标下,自变量名字是t,这不同于直角坐标下的x,需要注意。t本身代表角度,默 认单位是弧度(radians)。如果您想使用角度(degrees),可以执行下面的命令:

gnuplot> set angles degrees

下面我们看例子:

gnuplot> set polar
gnuplot> unset key
gnuplot> set samples 1000
gnuplot> set xrange [40:40]
gnuplot> set yrange [40:40]
gnuplot> set size square
gnuplot> plot t lw 2

从这里我们看出,t默认的取值范围是是[0:2*pi]。和直角坐标类似,改变t取值范围的命令是 set trange:

gnuplot> set trange [0: 10pi ]
gnuplot> replot

极坐标下的栅格和直角坐标不同,应该是按一定角度分隔的扇区,所以set grid命令需要加上 polar参数。默认扇区分隔角度是 30 度,该角度可以作为set grid polar的参数进行调整:

gnuplot> set grid polar pi /5
gnuplot> plot 5+25cos(5t /2) lw 2

22 参数方程

gnuplot也能画参数方程。首先设置参数方程环境:
gnuplot> set parametric

然后我们会看见返回信息:

dummy variable i s t f o r curves , u/v f o r s u r f a c e s

和极坐标类似,参数方程的自变量也是t。后面的u/v是用于3D绘图的参数方程自变量,我们目 前暂时不管它。 对于参数方程x = f(t), y = g(t),绘图命令为 plot f ( t ) , g ( t )

下面我们看一个例子,这是一个李萨如(Lissajous)曲线:

gnuplot> set parametric
gnuplot> set xrange [1. 2 : 1. 2 ]
gnuplot> set yrange [1. 2 : 1. 2 ]
gnuplot> set trange [ 0 : 2pi ]
gnuplot> set samples 1000
gnuplot> set size square
gnuplot> unset key
gnuplot> plot sin(3t ) ,sin(4t ) lw 2

23 误差条

Error bar是在图像上表现数据误差范围的一种方式。对于含有误差项的数据,除了通常的x 轴和y轴两列数据外,我们还需要有额外的误差数据列。 拿x数据列举例,如果误差用标准差x来表示,那么数据取值范围可以表示为 [xx, x+x],这时候只要增加一列误差项就行了,所以一共需要 3 列数据。如果误差用最小值xmin和 最大值xmax来表示,那么数据取值范围可以表示为[xmin,xmax],这时候需要增加两列误差项, 所以一共需要 4 列数据。对于y数据误差,表达方法和x类似。如果同时包含x和y误差,就需 要把两者结合起来。 在gnuplot里,error bar的基本使用方法是: plot “数据文件名” using<using参数> with<xerrorbars | yerrorbars | xyerrorbars >

using命令在之前的“多组数据绘图”博文里已经介绍过,目的是选择哪些列数据进行绘图,数据列数 必须和后面选择的绘图方式对应。with命令后面跟的是绘图方式,选择用xerrorbars,yerrorbars, 还是xyerrorbars。根据不同绘图方式,所需数据列数分别为:

 xerrorbars
  • 3 列:x y x

  • 4 列:x y xmin xmax

 yerrorbars
  • 3 列:x y y

  • 4 列:x y ymin ymax

 xyerrorbars
  • 4 列:x y x y

  • 6 列:x y xmin xmax ymin ymax

下面我们举一个例子,这是一个测量在液体中聚焦的脉冲激光在焦点处产生气泡几率的实验,数据 文件(probability.dat)如下:

### 文件开始Ave Energy Probability Min Energy Max Energy Energy SD(micro J) (%) (micro J) (micro J) (micro J)=======================================================================
9.08 0 8.96 9.15 0.06
10.00 2 9.91 10.08 0.05
10.52 3 10.41 10.60 0.06
11.03 10 10.90 11.11 0.06
11.52 25 11.38 11.62 0.07
12.03 57 11.90 12.13 0.07
12.52 88 12.38 12.64 0.08
13.01 93 12.86 13.09 0.07
13.51 100 13.38 13.61 0.08
14.52 100 14.38 14.67 0.08文件结束

x轴数据为激光能量,y轴数据为气泡产生几率,这里只有x误差,并且同时包含了最小最大 值和标准差。我们现在用最小最大值画图:

gnuplot> set xrange [ 8 : 1 6 ]
gnuplot> set yrange [5:105]
gnuplot> unset key
gnuplot> set xlabel " Laser ␣ Pulse ␣Energy␣ (J) "
gnuplot> set ylabel "Bubble␣Formation␣ Probability ␣ (%) "
gnuplot> plot " pr obab ilit y. dat" using 1 : 2 : 3 : 4 with xerrorbars
如果既要画error bar,又要连线,可以把上述命令中的errorbars换为errorlines:
gnuplot> plot " pr obab ilit y. dat" using 1 : 2 : 3 : 4 with x e r r o r l i n e s

24 拟合

gnuplot除了绘图功能之外,最简单实用的功能就是拟合了。gnuplot可以进行单变量甚至多变 量的线性和非线性拟合。虽然可能不像专门的数学软件那么强大,但是足以对付日常需要了。我们 拿上一讲里的数据来举例子。 首先,要定义一个待拟合的函数: gnuplot> f (x)=50(1+erf( a(xb) ) )

这里使用了误差函数erf(x),有两个待定的参数:a, b。下面我们生成一个文件“fit.par”,里面包含 的是参数a和b的初值:

a = 1 b = 12

初值的选择要尽可能贴近结果,否则可能导致误差甚至无法收敛。下面我们进行拟合:

gnuplot> fit [ 8 : 1 6 ] f (x) ’ pro babi lit y. dat ’ using 1:2 via ’ f i t. par ’

gnuplot里面关于拟合的命令是fit,后面的自变量取值范围不是必需的。f(x)函数已经在上面定义 过了,数据文件“probability.dat”也已经在上一篇博文中交代过了。via后面跟的是参数变量列表文 件。执行fit命令之后,gnuplot会输出一堆结果。我们忽略那些中间运算,只把最后结果贴在下 面:

After 5 iterations the fit converged. final sum of squares of residuals : 41.9399 rel. change during last iteration : -4.27973e-07

degrees of freedom (FIT_NDF) : 8 rms of residuals (FIT_STDFIT) = sqrt(WSSR/ndf) : 2.28965 variance of residuals (reduced chisquare) = WSSR/ndf : 5.24249

Final set of parameters Asymptotic Standard Error ======================= ==========================

a = 1.15661 +/- 0.06331 (5.474%) b = 11.9027 +/- 0.02383 (0.2002%)

correlation matrix of the fit parameters:

a b a 1.000 b 0.014 2.000

这段文字说明,经过 5 次迭代,gnuplot得到了收敛的结果。中间部分是参数a和b的最终取值以 及渐近标准差(asymptotic standard error)。渐近标准差的计算是基于线性拟合的,对于非线性拟 合,渐近标准差一般都比真的标准差小,所以这个数字只能用于定性分析。而最后给出的相关矩阵 (correlation matrix)可以帮助我们确认渐近标准差的可靠度,非对角元素绝对值越小,渐近标准 差越接近真实标准差。 好了,现在我们可以把数据和拟合曲线画在同一张图上了: gnuplot> set xrange [ 8 : 1 6 ] gnuplot> set yrange [5:105] gnuplot> unset key gnuplot> set xlabel “ Laser ␣ Pulse ␣Energy␣ (J) “ gnuplot> set ylabel “Bubble␣Formation␣ Probability ␣ (%) “ gnuplot> plot “ pr obab ilit y. dat” using 1 : 2 : 3 : 4 with xerrorbars , f (x) lw 2 l c rgb “ orange “

25 简单3D函数绘图

终于谈到3D绘图了。大多数情况下普通3D曲面绘图并不是一个好的选择,因为投影会使这样的绘图很难表达定量关系,通常只能定性的显示一下函数或者数据趋势。这种情况下,往往需要其他图像的配合才能展示定量的关系。我们从简单的函数图像入手,介绍一下gnuplot的3D绘图功能。

在3D情况下,gnuplot的绘图命令是splot:
gnuplot> f (x , y)=sin(sqrt(xx+yy) ) /sqrt(xx+yy)
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set zlabel "Z"
gnuplot> unset key
gnuplot> splot f (x , y)

显然,默认的网格有点过大,无法显示函数细节。这个网格大小可以通过isosamples参数来调 节。另外,底部平面似乎离曲面太远了,留了很大一段空白,我们想把这个空白缩小一些。底部平 面的位置由xyplane参数来控制,可以用:

set xyplane at <z坐标>

来设定底部平面的绝对位置,也可以用:

set xyplane <相对比例>

来设定空白部分相对于zrange的比例。下面是例子:

gnuplot> set isosamples 50
gnuplot> set xyplane 0.2
gnuplot> replot

由于网格是透明的,因此网格重叠部分显得比较混乱。为了更清楚的显示函数图像,我们让后面被遮挡的部分隐藏起来:

gnuplot> set hidden3d
gnuplot> replot

除了用网格表示曲面,我们还可以用色彩来表示不同的z值,gnuplot把这种表示方式叫做 pm3d(palette-mapped 3d):

gnuplot> set pm3d
gnuplot> replot

最后,既然是3D图像,就要涉及视角问题。gnuplot里的3D视角用set view命令控制,默 认视角是60, 30,分别表示绕x轴和z轴的旋转角度。另外,一些terminal例如wxt,支持直接用 鼠标拖动图像改变视角。

gnuplot> set view 45 ,20
gnuplot> replot

26 数据文件存储格式

在3D数据绘图之前,我们先谈谈gnuplot数据文件的存储格式。为什么在2D绘图时我们没 有涉及这个问题呢?因为2D绘图数据相对简单,只要有x和y两列数据就可以了。而3D绘图数 据量成平方增长,数据存储方式也更多样化。 gnuplot的数据可以以纯文本或者二进制方式存储。之前我们在2D绘图中均使用纯文本方式 存储数据,这样的好处是简单直观,把数据按照x和y存为两列就可以了。在3D情况下,由于数 据量激增,纯文本文件所占空间较大,读写速度也较慢,所以很多时候用二进制存储数据更方便。 无论纯文本还是二进制,存储数据的方式都不是唯一的,我们这里只介绍最常用的方式。

(一)纯文本格式:

2D的情况我们已经很熟悉了,这里说说3D的情况。3D情况下,x, y, z(x,y)可以按照下面格 式存储:

<x0> <y0> <z0,0> <x0> <y1> <z0,1> <x0> <y2> <z0,2> … … … <x0> <yN> <z0,N>

<x1> <y0> <z0,0> <x1> <y1> <z0,1> … … …

这里有几个要点:

  1. 每行存储x, y, z三个数据

  2. 首先保持x不变,让y逐行变化

  3. 当y遍历[y0, yN]取值范围后,x取[x0, xN]里的下一个值,重复过程 2

  4. 每个相同x取值的数据块之间,保留一个空行(这个比较容易忽视,需要注意)

然后就可以用splot命令绘制3D数据图了。

(二)二进制格式:

假设有NxM个数据(z值),数据逐行按照从左到右、从上到下的顺序存储在二进制文件中, 这时候绘制数据文件的命令为:

plot ’<filename>’ binary <二进制参数列表>
splot ’<filename>’ binary <二进制参数列表>

可能有人会问,绘制3D数据不是用splot吗?为什么这里还会用plot?我们暂且忽略这个问题, 来看看二进制参数列表。 二进制文件只是一个数据流,gnuplot可不知道我们数据的具体存储方式,这需要我们通过各 个参数告诉gnuplot。下面是一些常用参数:

  1. array=(N,M) 这是告诉gnuplot我们数据中x和y各自的维数

  2. format 我们的数据是 16 位还是 32 位?是整型还是浮点数?format参数负责告诉gnuplot这些信 息。我们可以通过执行下面的命令: show d a t a f i l e binary d a t a s i z e s

来获得format参数的数据类型列表。
  1. endian 对于多字节数据,一般有两种不同的字节存储顺序:big或者little。如果您试图绘制一个二 进制数据,而结果看起来莫名其妙,很可能就是endian设置错了。

  2. dx, dy, dz 这其实就是∆x,∆y,∆z,也就是各个坐标的比例系数。例如设置dx=2,而数据文件中x的 取值范围是[0:100],那么所绘图像上x的取值范围就会变为[0:200]。

下面是一个绘制二进制数据的例子:

splot " d a t a f i l e. bin " binary array =(64 ,64) endian=l i t t l e format="%f l o a t " with
l i n e s

27 3D数据曲面绘图及边框

理解了gnuplot的数据存储格式,我们可以来学习3D绘图了。我们拿一个6X6的数据举例, 该数据以纯文本方式存在此文件中:data3d.dat 3D数据曲面的绘制和3D函数曲面的绘制基本相同,所以我们无需多加解释,直接来看命令 和结果:

gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set zlabel "Z"
gnuplot> set xyplane 0.2
gnuplot> set hidden3d
gnuplot> set view 45 ,30
gnuplot> unset key
gnuplot> splot "data3d. dat" with l i n e s

曲面后面的部分由于遮挡,看不到。没关系,我们学过怎样调整视角:

gnuplot> set view 45 ,210
gnuplot> replot

这里还要讲讲边框的问题。在2D情况下我们曾经讲过可以通过unset border命令取消边框, 但是我们没有讲set border命令,因为这个只有在3D情况下才能说清楚。2D情况下只有 4 个边 框,而3D情况下,除了底部 4 个边框,还有竖直 4 个,以及顶部 4 个,所以总共 12 个边框。这 12 个边框显示与否,由一个12 bit的整数控制,例如:

 0000 0000 1111:只显示底部 4 个边框
 0000 1111 0000:只显示竖直 4 个边框
 1111 0000 0000:只显示顶部 4 个边框

不难看出,如果要显示所有 12 个边框,对应的二进制数就是:1111 1111 1111,换算成十进制就 是 4095 。set border命令之后紧跟这个整数,就可以控制显示哪些边框。另外,以前曾经讲过的和 linestyle有关的参数,都可以用来控制边框的显示风格:

gnuplot> set border 4095 l c rgb "#2554C7"
gnuplot> replot

28 Pm3d绘图

在3D函数绘图中我们介绍过,使用pm3d模式可以用色彩表示3D函数值的大小。数据绘图 也可以使用pm3d模式。我们这次就稍微详细介绍一下pm3d。 pm3d即Palette Map 3D,中文或叫“色板映射”。我们还是拿上一篇文章中的数据文件来举例 子:

gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set zlabel "Z"
gnuplot> set xyplane 0.2
gnuplot> unset key
gnuplot> set hidden3d
gnuplot> set pm3d
gnuplot> set view 45 ,210
gnuplot> splot "data3d. dat" with l i n e s

我们看到,本来的曲面被加上了颜色,不同的色彩对应不同的z值,这个对应关系显示在右边 的色彩条(color box)中。这里有个问题:我们的数据是6x6的,但是色彩块只有5x5,这个色彩 是怎样确定的呢?很简单,每个块的四个顶点取平均值,对应的色彩就是这个块的色彩。这个取值 方法不是唯一的,可以用corners2color参数来设定,详情请用help set pm3d命令查询。

色彩图除了画在曲面上,还可以画在底部或顶部(还记得3D图底部和顶部都有border吗?) 设置方法为:

set pm3d at b | s | t

b,s,t三个字母分别代表底部、曲面和顶部,at之后可以是任一个字母,也可是三个字母的任意组 合。例如:

gnuplot> set pm3d at bst
gnuplot> replot

当然,如果要看数据在取值范围内的全貌,最好的方法是从上往下看:

gnuplot> set pm3d map
gnuplot> set size square
gnuplot> replot

我们之前介绍过set view命令调整视角,这里的set pm3d map其实是包含set view map命令 在内的一系列命令组合。

我们注意到,右边的色彩条取值范围是[0.1:1],这是gnuplot自动设置的。如果我们想手动设 置这个范围呢?可能有人会想到set zrange,但是zrange控制的是画图时z的取值范围,而不是色 板对应的取值范围。其实,色板对应的取值范围是cbrange(Color Box range):

gnuplot> set cbrange [ 0 : 1 ]
gnuplot> replot

我们什么时候会想要手动设置cbrange呢?例如,我们需要比较两组数据的时候,我们一定希 望两张图上,相同数值对应的是相同的颜色。 最后,我们有时候可能觉得这样像“马赛克”一样的图片不那么好看。这时候,我们可以利用插 值,得到比较平滑的彩色图。使用插值的方法是:

set pm3d i n t e r p o l a t e N,M

M和N分别代表x和y方向插值的数目。如果希望gnuplot自动优化选择,就让M=N=0:

gnuplot> set pm3d i n t e r p o l a t e 0 ,0
gnuplot> replot

29 色板(palette)设置

pm3d绘图默认的色板看起来很不错,但是我们有时候还是希望能自己定义不同的色彩,这次 我们谈谈怎样自定义色板。 自定义色板的方式有好多种,我们这里只谈一下比较方便常用的方式:用rgbformulae定义 RGB色彩。 RGB是电脑中最常用的色彩空间表示方式,而rgbformulae是一系列从数值到色阶的数学映射 公式,共有 37 个。如果想知道rgbformulae到底包含哪些公式,可以使用gnuplot命令:

show p a l e t t e rgbformulae

由于RGB有三个颜色通道,所以每一个色板需要三个公式,分别表示R(Red)、G(Green)、B(Blue)。 色板的设置方法为:

set pa l e t t e rgbformulae r , g , b

其中r, g, b分别表示R, G, B通道所用公式代码( 0 到 36 ,允许用负值)。gnuplot默认色板的公 式代码为 7 , 5 , 15 。 37 个公式加上负值共有 733 个不同的组合方式,并不是每个组合都有好的显示效果,而我们仅 凭想象力是无法知道效果好坏的。这时候,test palette命令可以帮助我们预览一下显示效果。即使 如此,找到一个好的色板设置组合并不是一件很容易的事情。下面这些常用的组合可以给我们提供 一些帮助:

1. 7, 5, 15(pm3d默认)
2. 3, 11, 6(绿—红—紫)
3. 23, 28, 3(绿—蓝—白)
4. 21, 22, 23(黑—红—黄—白)
5. 30, 31, 32(黑—蓝—紫—黄—白,可以用于黑白打印)
6. 33, 13, 10(彩虹色)
7. 22, 13, -31(另一种彩虹色)
8. 34, 35, 36(黑—红—黄—白)

最后,如果我们不想用彩色,而只是想用黑白灰度,可以用下面的命令:

set pa l e t t e gray

30 Image绘图

在谈到pm3d绘图时我们说过,NxM的数据只能画出(N-1)x(M-1)的图像。有没有这样一种 方式,让我们能从NxM的数据画出NxM的图像呢?这次我们介绍一种新的画图风格:image。 咱们还是用以前用过的数据文件data3d.dat: gnuplot> unset key gnuplot> set xlabel “X” gnuplot> set ylabel “Y” gnuplot> set size square gnuplot> plot “data3d. dat” with image

这里我们看到,色块数目等于数据点数目,每一个色块中心位于相应数据点,而色块色彩对应的就是该数据点的值。这和pm3d不同,因为pm3d绘图时数据点位于色块顶点位置。另外,这里虽然用的是plot命令,但是图像反应了3D的信息,所以我们把它放在3D作图里介绍。这两种方式无法简单判断优劣,只能根据实际需要选择。当像素比较多而数据又比较平滑的时候,其实两者差别不大。除了image,还有两个非常类似的绘图方式:rgbimage和rgbalpha。image用于处理单色图(只有一个z值),可以包含x,y,z三列数据;rgbimage用于处理RGB彩色图,可以包含x,y,r,g,b五列数据;rgbalpha在rgbimage基础上增加了alpha通道(透明信息),可以处理透明RGB彩色图。除了一般数据文件,上述画图方式还支持直接读取png格式图片:

gnuplot> unset key
gnuplot> set title "Function␣y␣=␣x^2"
gnuplot> set xlabel "X"
gnuplot> set ylabel "Y"
gnuplot> set term wxt enhanced
gnuplot> plot x2 lw 2 ,\

“tux. png” binary f i l e t y p e=png center =(0 ,0) dx=0.002 dy=0.01 with rgbalpha , “tux. png” binary f i l e t y p e=png center =(1 ,1) dx=0.002 dy=0.01 with rgbalpha , “tux. png” binary f i l e t y p e=png center =(2 ,4) dx=0.002 dy=0.01 with rgbalpha , “tux. png” binary f i l e t y p e=png center =(3 ,9) dx=0.002 dy=0.01 with rgbalpha , “tux. png” binary f i l e t y p e=png center =(4 ,16) dx=0.002 dy=0.01 with rgbalpha

这里我们利用一个小企鹅的图片(tux.png)画了一个二次平方函数。binary文件格式我们以 前介绍过,这里有两个新的参数:filetype和center。filetype用于指定文件格式,而center用于指 定图片中心位置。

31 等高线图

等高线图是另一类重要的3D绘图方式。为了说明gnuplot里面等高线图的绘制方法,我们使 用下面这个数据文件作为例子:surface.dat 首先绘制普通曲面图: gnuplot> set hidden3d gnuplot> splot “ surface. dat” with l i n e s

下面加上等高线:

gnuplot> set contour base
gnuplot> splot " surface. dat" with l i n e s title ""

set contour命令之后除了base参数外,还可以使用surface或both参数,分别表示等高线画 在底面、曲面或者两者都画。这里设置了一个空的title,是为了在图例中不要显示文件名,以免和 等高线的图例混淆。 如果我们想在平面中显示等高线,可以使用下列命令: gnuplot> unset surface gnuplot> set viewmap gnuplot> set size square gnuplot> replot

如果我们想在之前提到过的pm3d图上显示等高线,可以这样做:
gnuplot> set pm3d at b
gnuplot> set key at screen 0. 8 , 0. 8
gnuplot> replot

这里我们把图例的位置做了调整,因为默认图例是在图像里面的,这样可能影响我们的图像显示。

最后,我们谈谈怎样手动设置等高线数值和间距。等高线的数值间隔参数设置命令是set cntrparam levels。默认情况下,gnuplot自动设置等高线数值。如果要进行手动设置,有两种方 法:

  1. incremental <start>,<incr>,<end> 设置起始值以及间隔大小,这种方法适用于等间隔的等高线;

  2. discrete <z1>,<z2>,<z3>,… 分别设置各个等高线数值,这种方法适用于间隔不等的等高线。

例子:

gnuplot> set cntrparam l e v e l s incremental 2 ,0.5 ,2
gnuplot> replot

32 等高线的颜色

上一讲最后我们提到了怎样改变等高线的数值间距。不同等高线是由颜色来区分的,而默认的颜色未必是最理想的组合,我们还用上次的数据文件举例:

gnuplot> set contour
gnuplot> unset surface
gnuplot> set size square
gnuplot> set key at screen 0. 8 , 0. 8
gnuplot> set viewmap
gnuplot> splot " surface. dat" with l i n e s title ""

这里有些默认的颜色太浅了,看不清楚。下面我们想办法把它们加深加粗。细心的读者可能注意到,这里默认的等高线颜色和上一讲中的不同。等高线的默认颜色是这样确定的:按照色彩编号(如果不记得了,请复习一下我们以前讲过的“点线风格”)从低到高,而最低的色彩比曲面(surface)颜色大一号。这里虽然曲面没有画出来,但是仍然占去了 1 号颜色,所以等高线颜色从 2 号颜色(绿色)开始。而上一讲中,我们设置了hidden3d参数,曲面上下面分别使用不同的颜色,因此曲面占去 2 个颜色,等高线从 3 号颜色(蓝色)开始。我们现在要做的就是要gnuplot使用我们自定义的颜色,而不是系统默认的颜色。下面看代码:

gnuplot> set style l i n e 1 lw 2 l c rgb " red "
gnuplot> set style l i n e 2 lw 2 l c rgb " forestgreen "
gnuplot> set style l i n e 3 lw 2 l c rgb " blue "
gnuplot> set style l i n e 4 lw 2 l c rgb "magenta"
gnuplot> set style l i n e 5 lw 2 l c rgb "darkcyan"
gnuplot> set style l i n e 6 lw 2 l c rgb " goldenrod "
gnuplot> set style increment u s e r s t y l e s
gnuplot> replot

我们这里首先自定义了一系列linestyle(参考第十八讲“图例”),然后用set style incrementuserstyles命令告诉gnuplot使用我们自己定义的曲线风格,而不是默认风格。这样,我们得到了我们想要的效果。 这里我们并没有使用RGB直接定义颜色,而是用了一系列色彩的名字(colornames),这些colornames是gnuplot预定义的一些RGB颜色。如果想知道到底有哪些预定义的颜色,可以使用下面的命令:

gnuplot>show pa l e t t e colornames

其实不仅限于等高线,只要是在同一个图上画多个函数或数据,都可以用这种方法设置显示风格。

33 Table输出

gnuplot作为一个绘图软件,一般都是读取数据,把图像输出到指定的terminal。但是gnuplot也可以把图像以table形式存储到一个数据文件中。这样做的好处是方便我们对图像数据进行进一步处理,得到我们想要的效果。我们之前画等高线图所用的surface.dat文件,其实就是通过这种方式得到的。还以surface.dat数据的等高线图为例,contour模式只能在splot命令中使用。如果我们把等高线图预先以table格式存入一个文件,我们就可以对其进行适当处理,并且可以用plot命令绘图:

gnuplot> set contour base
gnuplot> unset surface
gnuplot> set table ’ cont. dat ’
gnuplot> splot ’ surface. dat ’
gnuplot> unset table
gnuplot> unset key
gnuplot> set size square
gnuplot> set xrange [4:4]
gnuplot> set yrange [4:4]
gnuplot> plot ’ surface. dat ’ with image , ’ cont. dat ’ with l i n e s lw 1.5 l c rgb ’
yellow ’

这里我们预先把等高线图以table格式存入了cont.dat文件,随后用plot命令调用该文件,把等高线画在了surface.dat数据的image图上(注意:不是pm3d图)。这里我们可以用plot命令的图线风格参数控制等高线的粗细和颜色。这里我们没有像以前那样用不同颜色区分等高线,而是所有等高线使用了同一颜色。那么怎样区分各个等高线呢?我们可以用label标注等高线数值。label的使用方法我们在第十五讲“坐标系统及标签”里介绍过,但是直接手动设置label有点麻烦。下面这个网页里的label_contours.awk文件是一个AWK脚本文件,可以帮助我们自动设置标签:http://gnuplot.sourceforge.net/scripts/index.html#tricks-here我们这里不打算介绍AWK脚本语言,也不打算介绍这个脚本的具体使用方法,因为该网页以及该文件内已经包含了详细的使用说明。我们只给出一个使用该脚本得到的带标注的等高线图:

34 多图(multiplot)

之前我们曾用plot命令将多个曲线画在同一张图上,这次我们谈谈怎样将多个图画在一起。这样做的主要目的是把不同的信息放在一起,以方便比较。我们首先看看怎样把几张图像矩阵一样排列起来:

gnuplot> set multiplot layout 2 ,2
gnuplot> plot sin(x)
gnuplot> plot sin(2x)
gnuplot> plot cos(x)
gnuplot> plot cos(2x)
gnuplot> unset multiplot

set multiplot命令告诉gnuplot进入多图模式,这时候我们画的所有图像都会在出现在同一张画布上。如果不做调整,所有图像将重叠在一起;如果适当调整每个图像的位置和大小,图像将按我们的要求排列起来。layout参数可以自动将几幅图按照指定格式排列起来,例如这里的 4 幅图排成了 2  2 的格式。最后,unset multiplot命令退出多图模式。之前我们用过的绘图命令在多图模式下都有效,包括将图片输出为不同格式。如果不用layout参数,我们还有更灵活的排版方式,例如下面这个“画中画”的例子:

gnuplot> reset
gnuplot> set multiplot
gnuplot> unset key
gnuplot> plot ’ spectrum. dat ’ with l i n e s
gnuplot> set xrange [ 6 6 0 : 7 4 0 ]
gnuplot> set xtics 20
gnuplot> set yrange [200:2000]
gnuplot> set ytics 500
gnuplot> set o r i g i n 0. 2 , 0. 4
gnuplot> set size 0. 4 , 0. 4
gnuplot> replot
gnuplot> unset multiplot

这里我们绘制了一组光谱数据(spectrum.dat),并且把[660, 740]这个区间内的数据单独绘制出来,嵌套在大图内,用于更清楚的展示细节。这里的set origin命令用于设置绘图的原点,setsize命令以前已经讲过,用于设置图像大小。这两个命令均使用screen坐标系统(参考之前的博文:“坐标系统及标签”)。开始处的reset命令正如它的名字所暗示的那样,用于让人工设置的参数恢复至默认值。如果想更多了解multiplot命令的用法,请使用help multiplot命令。

35 曲线色彩填充

目前我们所涉及的主题都是比较基本的,应该覆盖了大部分科学绘图的需要,而gnuplot的功 能还远不止如此。从现在开始,我们介绍一些稍微高级些的应用,其中有些可以让我们的绘图更加 丰富多彩,有些能让我们的工作更有效率。 这次我们介绍一下填充曲线(filledcurves)。我们使用在“多组数据绘图”中用过的数据文件 “precipitation.dat”作为例子:

gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ using 1:3 with f i l l e d c u r v e s

这里的filledcurves是一种新的画图风格,它会在数据(或函数)曲线中填入指定颜色。默认 情况下,曲线是自我封闭的(closed),所以这里的例子中首尾数据点被连接了起来。 我们也可以指定填充曲线和某条水平或竖直直线之间的区域: gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ using 1:3 with f i l l e d c u r v e s y1=0

这里曲线和横轴之间的区域被填充了颜色。这里的y1也可以是x1, x2, y2,它们所代表的意义 在“第二坐标轴”中介绍过。 除此之外,也可以指定曲线和某点之间的连接区域: gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ using 1:3 with f i l l e d c u r v e s xy=6,60

如果提供两组数据,还可以在两组数据之间的区域填充颜色:

gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ using 1 : 2 : 3 with f i l l e d c u r v e s

如果我们希望当第一组数据小于第二组时使用一种颜色,而第一组数据大于第二组时使用另一种颜色,我们可以这样做:

gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ using 1 : 2 : 3 with f i l l e d c u r v e s below , ’ ’ using
1 : 2 : 3 with f i l l e d c u r v e s above

这里的below和above参数表示只填充相应(低于或高于)的区域。plot命令第二部分的数据 文件名为空,这是因为该文件和第一部分是相同的,我们可以把文件名省略。 我们虽然得到了具有填充色的曲线,但是这样大红大绿的效果并不是我们想要的。我们下一次 就讲讲怎样设置填充风格,让它们看起来更好看一点。

36 填充风格

正如曲线风格的设置命令是set style line,色彩填充风格的设置命令是set style fill。我们仍然 以“precipitation.dat”文件举例:

gnuplot> set style f i l l s o l i d 0.4
gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ using 1:2 with f i l l e d c u r v e s y1=0 lw 2 l c rgb
"orangered " , ’ ’ using 1:3 with f i l l e d c u r v e s y1=0 lw 2 l c rgb " purple "

这里的solid参数表示用纯色填充,后面的数字取值范围从 0 到 1 ,表示色彩深浅。默认情况 下,填充色和曲线颜色是相同的。 这里有个问题:第一组数据有一部分被第二组数据覆盖住了。有些terminal(例如wxt, png, pdf等)支持透明效果,可以解决这个问题。

gnuplot> set style f i l l transparent s o l i d 0.4
gnuplot> replot

这里使用了transparent参数,相应的solid后面的数字就变成了表示透明度(alpha值)的参 数。 如果我们希望填充区域不要有边线(曲线本身),那么可以使用noborder参数: gnuplot> set style f i l l transparent s o l i d 0.4 noborder gnuplot> replot

如果需要黑白打印,我们可能希望不要用纯色填充,而是用不同的花纹填充,这时我们可

以使用pattern参数。pattern参数之后可以跟一个数字,表示起始使用的pattern编号。不同的 terminal有不同的花纹效果,可以在某terminal下使用test命令查看该terminal支持哪些花纹。 下面是例子:

gnuplot> set style f i l l transparent pattern 1 border
gnuplot> replot

37 柱状图

除了点线图外,柱状图也是一种常用的作图方式。我们还用前两讲用过的“precipitation.dat” 数据文件作例子:

gnuplot> set style data histogram
gnuplot> set style histogram c l u s t e r e d gap 1
gnuplot> set style f i l l s o l i d 0.4 border
gnuplot> plot " p r e c i p i t a t i o n. dat" using 2 , ’ ’ using 3
set style data histogram命令告诉gnuplot所有数据绘图都使用histogram风格。set style
histogram命令设置histogram作图的参数,例如clustered模式就是像上图那样,把几组数据并排
画在一起,gap 1就表示各簇数据之间空白的宽度等于数据柱宽度的 1 倍。填充风格命令(set style
fill)上次我们已经介绍过了。
这里我们发现一个histogram和一般点线作图的不同:一般点线作图,每个图都要提供x,y两
组数据,而histogram图只需要提供一组数据,每个数据自动画在X轴上的非负整数位置。这时
候,X轴上的标注并不是我们想要的,图例中的标注也不符合我们的要求。我们以前在“坐标取值
范围及刻度”和“多组数据绘图”讲过,这两处的标注,可以分别用set xtics命令和title参数来设
置。这里提供另一种改变标注的方法,我们把“precipitation.dat”文件稍微修改一下:

文件开始

各城市月平均降水量 (mm)
月份 北京上海
======================
一月 2.5 38.1
二月 5.1 58.4
三月 10.2 81.3
四月 25.4 101.6
五月 27.9 114.3
六月 71.1 152.4
七月 175.3 129.5
八月 182.9 132.1
九月 48.3 154.9
十月 17.8 61.0
十一月 5.1 50.8
十二月 2.5 35.6

文件结束

我们把修改后的文件称作“precipitation_v2.dat”。和原文件相比,这里有两处改动:
  1. 原文件中包含城市名称的一行是注释掉的,新文件里这一行表示注释的#字符被去掉了;

  2. 原文件中第一列用阿拉伯数字表示的月份,新文件里被换作了中文月份名称。

下面来看新的例子:

gnuplot> plot " precipitation_v2. dat" using 2: x t i c l a b e l s (1) title columnheader
(2) , ’ ’ using 3: x t i c l a b e l s (1) title columnheader (3)

这里using参数的数据列号后面,增加了一个新的xticlabels(1),这表示使用第 1 列的内容作 为每个数据的X轴标注。另外,title参数后面跟了一个columnheader(n)函数,这表示使用第n 列的第一行内容作为每组数据的title。这样,我们可以把每组数据的横轴和图例标注预先存入数据 文件中,画图时再调用。 除了clustered模式,histogram作图还有rowstacked模式,就是把几组数据竖着垒起来: gnuplot> set style histogram rowstacked gnuplot> set boxwidth 0.8 r e l a t i v e gnuplot> set xtics rotate by 45 gnuplot> replot

rowstacked模式没有gap参数,我们这里使用set boxwidth命令设置数据柱相对宽度。同 时,X轴标注被旋转了 45 度。这在柱状图里很常见,因为密排的柱状图往往没有足够的空间显示 X轴标注,旋转之后显示空间便增大了。

既然有rowstacked,有没有columnstacked呢?答案是有的。rowstacked逐行把数据叠加显 示,而columnstacked逐列把数据叠加。除此之外,还有errorbars模式,在clustered基础上增加 误差条。由于这两种模式和之前讲过的很类似,所以就不举例了。

38 阶梯图

和柱状图(histogram)相似的,还有阶梯图,英文叫做step或者stair图。这种作图方式经常 用于绘制数字化的离散变量。gnuplot里面有三种对应的作图方式,分别为:steps,fsteps,histeps。 另外,gnuplot里面还有一种和histogram更为相似的方式:boxes,我们在这里一并介绍。 下面,我们还是用“precipitation.dat”数据文件作为例子,来看看这几种作图方式有什么异 同:

gnuplot> set term wxt size 640 ,640
gnuplot> set xrange [ 0 : 1 3 ]
gnuplot> set xtics 1
gnuplot> set ytics 50
gnuplot> set multiplot layout 4 ,1
gnuplot> set tmargin 1
gnuplot> set style f i l l s o l i d 0.5
gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ u 1:3 with steps t " Style : ␣ steps "
gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ u 1:3 with f s t e p s t " Style : ␣ f s t e p s "
gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ u 1:3 with histeps t " Style : ␣ histeps "
gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ u 1:3 with boxes t " Style : ␣boxes"
gnuplot> unset multiplot

我们可以看出,三种steps作图方式基本相同,只是在X轴方向上略有平移。steps曲线先沿 X方向前进,再沿Y方向前进;fsteps曲线先沿Y方向前进,再沿X方向前进。虽然我们有 12 个数据点,但是steps和fsteps都只有 11 段表示Y值大小的横线。histeps和steps类似,但是起 始点前移了0.5个单位长度,因此histeps具有全部 12 段表示Y值大小的横线。这三种steps方 式都不具有填充风格。boxes和histeps几乎完全相同,不同点在于boxes可以使用填充风格。另 外,boxes的柱宽可以通过set boxwidth命令调节。 boxes和histogram风格的主要区别在于,histogram更多用于多组数据的比较,而boxes更多 用于单组数据的展示。

39 数据平滑

gnuplot是一个绘图软件,数据处理不是它的长项,但是它也可以做一些简单的数据处理工 作,例如之前提到过的拟合。这次我们谈谈另一种常用的数据处理:数据平滑。 数据平滑,就是根据一组数据,绘制出一个比较平滑的曲线。它有很多种不同的算法,一般可 分为两类:

  1. 根据数据绘制出一个近似的平滑曲线,曲线没必要通过每一个数据点;

  2. 曲线通过每一个数据点,在数据点之外通过插值获得平滑的曲线。

gnuplot里面数据平滑的命令是smooth,后面紧跟着一个表示具体算法的参数。下面我们来看例 子,还是用“precipitation.dat”数据文件:

gnuplot> set xrange [ 0 : 1 3 ] gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ u 1:2 smooth bezier lw 2 t ’ bezier ␣ curve ’ ,\

’ ’ u 1:2 smooth c s p l i n e s lw 2 t ’ c s p l i n e s ␣ curve ’ , ’ ’ u 1:2 w points pt 7 t ’ data␣ points ’

这里有两种平滑算法:bezier和csplines,分别对应上述两个类别。smooth默认使用lines风格绘 图。 另外,还有一种acsplines算法,平滑方式介于上述两者之间。这种算法除了x和y两组数据 外,还要求第三组数据,作为权重(weight)。当然,我们的文件里没有这一组“权重”数据,所以 我们手动给所有数据加上相同的权重: gnuplot> plot ’ p r e c i p i t a t i o n. dat ’ u 1 : 2 : ( 1. 0 ) smooth a c s p l i n e s lw 2 t ’ weight ␣= ␣ 1.0 ’ ,\

’ ’ u 1 : 2 : ( 6. 0 ) smooth a c s p l i n e s lw 2 t ’ weight ␣=␣ 6.0 ’ , ’ ’ u 1 : 2 : ( 6 0. 0 ) smooth a c s p l i n e s lw 2 t ’ weight ␣=␣ 60.0 ’ , ’ ’ u 1:2 w points pt 7 t ’ data␣ points ’

using参数里的括号是必要的,否则gnuplot会把括号内的数字当成列编号,而不是数字。 这里我们看到,在acsplines算法里,数据的权重越小,曲线越平滑,越像bezier;而数据的权 重越大,曲线越接近数据点,也就越像csplines。 smooth除了上述算法,还有其他选项,我们下次再介绍。

40 统计直方图

gnuplot里的histogram命令只是一种作图风格,它并不能计算数据的分布并画出直方图。要 完成这个任务,我们需要借助smooth命令。 上次我们介绍了smooth命令的几个参数。其实smooth命令不仅可以做数据平滑,也可以进 行一些统计计算。这次我们介绍smooth的另外两个参数:frequency和cumulative。 这两种参数都要求有两列数据:X和Y。对于同一个X值(例如X=xi),如果有不止一个 数据点(yi 1 ,yi 2 ,.. .),那么frequency参数就会把X=xi的所有数据点的Y 值相加,得到一个 X=xi处Y 值的和。如果我们让yi 1 =yi 2 =: : :=常数,那么这个和就可以用来表示数据点出现 在X=xi的频率。如果用cumulative参数,那么所有X < xi的数据点都会计算在内。 现在我们来看例子: gnuplot> set samples 300 gnuplot> set xrange [ 1 : 3 0 0 ] gnuplot> set format x “%.0 f “ gnuplot> set table “randomint. dat” gnuplot> plot int(10rand(0) ) gnuplot> unset table

这里我们生成了 300 个 0 到 9 之间的随机整数的序列,并把它存入了名为 “random-int.dat”的文 件。这里的rand()是gnuplot自带的伪随机数生成函数,能生成 0 到 1 之间的随机数。int()为取 整函数。下面我们来绘图:

gnuplot> reset
gnuplot> set boxwidth 1
gnuplot> set style f i l l s o l i d 0.5
gnuplot> set grid ytics
gnuplot> set xrange [1:10]
gnuplot> plot ’randomint. dat ’ u 2 : ( 1 ) smooth frequency w boxes t " frequency "

在plot命令里,我们用生成的随机数作为X,用常数 1 作为Y,这样smooth frequency就给 出了 0 到 9 之间各个数字出现的次数。我们再来看cumulative:

gnuplot> set yrange [ 0 : 3 5 0 ]
gnuplot> plot ’randomint. dat ’ u 2 : ( 1 ) smooth cumulative w boxes t " cumulative "

smooth cumulative把所有X小于某一数值的Y 值累计起来,所以最后达到最大值 300 ,正好 是样本总数。 上面的例子是整数样本,比较容易操作。对于实数(浮点数)样本,我们面临binning的问 题,这类似于将模拟信号转换为数字信号。下面我们用gnuplot源文件中自带的demo目录里的数 据文件“random-points”举个例子。“random-points”文件包含几组不同分布的随机数,其中第 2 列 为正态分布,共 300 个数据。

gnuplot> set autoscale
gnuplot> bin (x , s ) = sint(x/ s )
gnuplot> set boxwidth 0.05
gnuplot> set key l e f t top

gnuplot> plot ’randompoints ’ u ( bin ( $2 , 0. 0 5 ) ) : ( 2 0 / 3 0 0. ) s f w boxes t “ frequency “ ,\

’ ’ u 2 : ( 1 / 3 0 0. ) s cumul t “ cumulative “ lw 2 l c rgb “ royalblue “

注意:我们这里的plot命令用了大量缩写。我们先定义了一个函数bin(x,s),用于将模拟信号
数字化,其中s是每个bin的宽度(或者叫做样本间隔)。set boxwidth设定图中每个柱的宽度,
我们以前曾经用它设定过相对宽度,这里设定的是绝对宽度。
在frequency图中,X是数字化之后的数据,Y 是常数20/300.(注意这里的小数点)。分子
上的 20 是因为X被乘了0.05,为了保持每个直方柱面积不变(直方图中用面积表示概率),我们
把Y 乘以 20 ;分母上的 300 是样本总数,用于归一化,这样我们得到的就是分布概率,而不是某
区间内数据点的个数。
在cumulative图中,X数据binning没有必要,只需要将所有数据累加就可以了,而Y 是归
一化常数。
这样,这两种图的意义就非常清楚了:frequency给出的是概率密度函数,而cumulative给出
的是累计分布函数。

41 三元算符和分段函数

分段函数在若干区间上有不同的表达式,例如符号函数:

sgn(x) =
8><>:
 1 ifx < 0
0 ifx= 0
1 ifx > 0
gnuplot预定义函数中包含符号函数sgn(x),下面我们试着画一下函数图像:
gnuplot> set samples 1000
gnuplot> set xrange [1. 5 : 1. 5 ]
gnuplot> set yrange [1. 5 : 1. 5 ]
gnuplot> plot sgn(x) lw 2
gnuplot把所有取样点连接了起来,这样函数图像在零点成了连续的,而实际上零点应该是不
连续的断点。为了更合理的表现函数性质,我们需要用到三元算符(ternary)。三元算符的形式
是:
A?B:C
A一般是一个逻辑表达式,如果A为真,那么整个表达式的值为B;如果A为假,那么整个表达
式的值为C。这和C语言的问号表达式完全相同。
下面我们看如何用三元算符构造分段函数:
gnuplot> unset border
gnuplot> set zeroaxis l t  1
gnuplot> set xtics axis 1 ,2 ,1
gnuplot> set ytics axis 1 o f f s e t 0 ,0.5
gnuplot> set arrow 1 from 0 ,0 to 1.5 ,0 f i l l e d
gnuplot> set arrow 2 from 0 ,0 to 0 ,1.5 f i l l e d
gnuplot> plus (x) = x>0? 1 : 1/0
gnuplot> minus (x) = x<0? 1 : 1/0
gnuplot> set label 1 at 0 ,0 point pt 7 ps 1.5 l c rgb " red " front
gnuplot> plot plus (x) lw 2 l c rgb " red " title "sgn (x) " , minus (x) lw 2 l c rgb "
red " n o t i t l e
这里我们用plug(x)和minus(x)分别表示函数的正值和负值部分,用1/0表示函数值没有定
义。在零点,我们利用一个不含任何字符的label命令画一个独立的点。以前我们讲过label命
令,这里的label命令有两个新的参数:point参数允许在label所在坐标画一个点;而front参数
表示将label放在前景,这样它就不会被图像其他部分遮盖,类似于图形处理软件中调整layer的顺
序。和front类似的参数还有back。

42 几何图形对象

通过设置对象(object),可以让gnuplot在图中绘制几何图形。目前object支持四种几何图 形:rectangle(长方形),ellipse(椭圆形),circle(圆形)和polygon(多边形)。下面通过实 例说明它们的用法:

gnuplot> set grid
gnuplot> set size square
gnuplot> set object 1 rectangle from 0 ,0 to 4 ,3 lw 3
gnuplot> set object 2 rectangle at 4 ,3 size 4 ,3 behind
gnuplot> set object 3 e l l i p s e at 5, 5 size 6 ,3 angle 30 lw 2 \

f i l l c o l o r rgb “ red “ f i l l s t y l e transparent s o l i d 0.4 gnuplot> set object 4 c i r c l e at 3, 3 size 3 f c rgb “ blue “ f s transparent s o l i d 0.4 noborder gnuplot> set object 5 c i r c l e at 5, 5 size 3 arc [ 0 : 6 0 ] f c rgb “ orange “ f s s o l i d gnuplot> set object 6 c i r c l e at 5, 5 size 3 arc [ 6 0 : 2 0 0 ] f c rgb “brown” f s s o l i d gnuplot> set object 7 c i r c l e at 5, 5 size 3 arc [ 2 0 0 : 3 6 0 ] f c rgb “ forestgreen “ f s s o l i d gnuplot> set object 8 polygon from 1,1 to 1,5 to 3,8 to 8,6 to 5,4 to 7,0 to 1,1 lw 4 f c rgb “ v i o l e t “ gnuplot> plot [10:10][10:10] 15 n o t i t l e

这里共设置了 8 个对象,现在分别说明各个对象的用法:

 对象 1 和 2 是长方形,既可以通过对角顶点坐标,也可以通过中心坐标和宽高来设置。对象

2 的behind参数类似之前讲过的front和back。behind和back的不同在于,back仅仅是放
在曲线和label之后,而behind是放在所有图像元素之后。
 对象 3 是椭圆形,参数和长方形类似,多了旋转角度angle和填充风格。
 对象 4 是圆形,通过圆心坐标和半径设置。
 对象 5 、 6 、 7 也是圆形,但是多了arc参数指定圆弧角度,所以其实画出的是扇形。gnuplot
本身没有“饼图”(pie chart)这种风格,所以利用圆形对象可以绘制简单饼图。
 对象 8 是多边形,通过指定各顶点坐标来设置,注意多边形必须是闭合的。

设置的各个对象必须通过plot命令才能显示出来,而我们又不希望画什么其它图像,所以这里用一 种特殊方式,在绘图区域仅显示出各个几何对象。以前我们都是用set xrange(或yrange)命令来 设置坐标取值范围,其实这个取值范围也可以直接在plot命令中给出。这里我们通过在取值范围之 外画一条直线的方式,得到了一个仅包含各几何对象的图。

43 地图及圆圈数据图

上次我们讲了几何图形对象,这次我们介绍一种使用几何图形表示数据的方法。下面这幅图来

自美国地质调查局网站,显示的是前三天内(至本文写作时)世界各地发生的 4 级以上地震:

现在,我们用gnuplot绘制一张类似的地图,用圆圈大小和颜色表示震级,在地图上标注各地震发 生的位置。gnuplot的demo目录里有一个world.dat文件,包含世界地图的信息,我们就用它来绘 制地图。 随着我们学习的gnuplot命令越来越多,绘制一张图的命令越来越复杂。我们可以把所有命令 预先存入一个文件中,随后在gnuplot里面调用该文件,这样可以方便我们重复使用这些命令。我 们把下面这些命令存入名为“commands.gnu”的文件:

rgb ( r , g , b) =65536int( r )+256int( g )+int(b)
red (x) = 2/3.<=x && x<1? 255(3 3 x) : 255
green (x) = 0<=x && x<1/3.? 255 : x<2/3.? 255(2 3 x) : 0
blue (x) = 0<=x && x<1/3.? 255(1 3 x) : 0
c i r c l e c o l o r (x) = rgb ( red (( $32) /5.0) , green (( $32) /5.0) , blue (( $32) /5.0) )
unset key
set xrange [180:180]
set yrange [90:90]
set style f i l l transparent s o l i d 0.6 noborder
set object 1 rectangle from graph 0 ,0 to graph 1 ,1 f c rgb " lightcyan" behind
plot ’ world. dat ’ with f i l l e d c u r v e s l c rgb " forestgreen " ,\
’ earthquakes. dat ’ using 1 : 2 : ( ( $33)2) : ( c i r c l e c o l o r ( $3 ) ) with c i r c l e s l c rgb
variable

随后启动gnuplot,输入下面的命令:

gnuplot>load ’commands. gnu ’

这里的load命令用来调用刚才预存的文件。于是,我们得到下面这幅图:

现在,我们来解释刚才用到的那些命令:

 1 至 5 行定义了一个从数字到rgb颜色的映射,这类似于我们之前“色板设置”里讲过的
rgbformulae,只不过在这里我们使用了自己定义的函数。从这里我们也可以看到rgbformulae
的工作原理。在函数定义中我们使用了“三元算符和分段函数”讲过的问号表达式,可以作为一
种复习。
 在set object命令里我们定义了一个布满整个绘图区域的长方形,并且放置到了behind位
置,相当于为图像增加了一个背景颜色。
 plot命令里的前半部分用于绘制地图轮廓,后半部分用于绘制表示地震的圆圈。地震数据来
源于美国地质调查局网站,存于名为“earthquakes.dat”的文件中。
 这里用到了一个新的绘图风格:circles。圆圈的大小由using参数的第 3 列数据指定,圆
圈的颜色由linecolor参数设置。然而,这里没有指定具体的颜色,而是用了一个特殊的变
量——variable。variable的值由额外的一列数据(即using参数的第 4 列数据)指定,因此
颜色会随着不同数据改变。

把我们用gnuplot绘制的地图和原图比较一下,地震的位置是一致的。

44 for循环

作为一个具有脚本编程能力的命令行程序,循环语句是必不可少的。gnuplot具有和C语言类 似的for循环结构,可以应用于plot, splot, set和unset命令。for命令的基本结构是:

f o r [ i = begin : end : step ]

这表示i的取值从begin到end,步长为step。如果步长为 1 ,step也可以省略。下面举例说明:

gnuplot> f (x , s ) =exp(xx /(2.s ) ) /(sqrt(2pis ) )
gnuplot> set term wxt enhanced
gnuplot> set title "Normal␣ Distribution "
gnuplot> set samples 1000
gnuplot> set style f i l l transparent s o l i d 0.3 noborder
gnuplot> plot f o r [ i =1:10:3] f (x , i ) w f i l l e d c u r v e s title "^2 = ". i

plot命令里的i取值分别为1, 4, 7, 10。值得注意的还有后面的title参数,这里的小数点(.) 表示将两个字符串连接合为一个。有人可能会想:i不是整数吗?在gnuplot里面,数据类型可能 根据环境发生变化,例如这里的整数i用在了字符串操作中,就被当作字符串处理了。但是,如果 把这个i放在小数点前面,这种类型转换就不成立了。我不清楚这种情况的具体成因,但是有一个 办法可以解决这个问题,就是在i之前再加一个空的字符串,避免i成为字符串连接算符(小数 点)的第一个元素。 除了上面的形式,for命令还有一种字符串形式,例如:

gnuplot> plot f o r [ filename in " f i l e 1. dat␣ f i l e 2. dat␣ f i l e 3. dat" ] filename with
l i n e s

这里就绘制了三个数据文件的图像。

45 动画和reread循环

上一讲提到的for循环只能用于plot等有限的几个命令。如果循环体是一组命令,我们需要 用到reread。reread的作用就是让gnuplot返回到脚本文件最开始的地方,类似于某些编程语言的 goto命令。为了形成有效的循环(而不是死循环),reread命令需要配合if条件判别式。下面我 们利用reread命令,举一个生成动画的例子。我们建立两个脚本文件:

  1. 文件名”animate.gnu”:

    set term g i f animate delay 10
    set output "animate. g i f "
    set samples 1000
    set xrange [ 0 : 4pi ]
    unset key
    set tics t e x t c o l o r rgb " orange "
    set border l c rgb " orange "
    set grid l c rgb " orange "
    i=0
    load ’ looper. gnu ’
    set output
    
  2. 文件名”looper.gnu”:

    set object 1 rectangle from screen 0 ,0 to screen 1 ,1 f c rgb "gray10"
    behind
    plot sin(x+ipi /20) lw 3 l c rgb " green " n o t i t l e
    i=i+1
    i f ( i <40) reread
    

为了生成动画,我们使用了一个新的终端:gif。参数animate说明要生成动画,delay参数指定每 两帧图片之间的时间间隔,单位是1/100秒。循环体放在一个单独的文件里(looper.gnu),由指 标i控制循环次数,一共循环执行 40 次。gnuplot里的if条件句的用法和C语言是相同的,并且也 支持else和else if语句。这里的if语句只包含一个命令,如果if之后有多个命令需要执行,之间 用分号(;)隔开。 现在我们启动gnuplot,输入下面的命令: gnuplot>load ’ animate. gnu ’

这里是生成的动画:http://image.sciencenet.cn/album/201201/26/024121diddwbfdcbdtmo2i.gif

A 附录:互联网资源

  1. not so Frequently Asked Questions

  2. Impossible gnuplot graphs

  3. Gnuplot tricks blog

  4. Gnuplot surprising

  5. Gnuplotting