在同一图像中包含多组数据或函数时,图例是必要的。我们这一次谈一谈图例的微调。 这次来画前 3 阶的第一类贝塞尔函数 J n (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 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 line 1 lw 2 lc rgb "#F62217" gnuplot set style line 2 lw 2 lc rgb "#D4A017" gnuplot set style line 3 lw 2 lc rgb "#2B60DE" gnuplot plot besj0(x) ls 1 t "J_0(x)", besj1(x) ls 2 t "J_1(x)", besj2(x) ls 3 t "J_2(x)" 之前我们讲过, plot 命令后面可以跟随一些参数(例如 linewidth , linecolor 等)来改变点线风格。在上面的例子中,我们把这些参数单独拿出来放到了 set style 命令里,定义了三个 linestyle ,然后在 plot 命令里再调用这些 linestyle 。这样子做和我们之前的做法效果上没什么不同,唯一的区别是让 plot 命令短了一些。另外,改变风格可能容易一点。 上面是默认的图例,下面让我们进行微调。 为图例加上边框 gnuplot set key box gnuplot replot 改变图例显示位置 gnuplot set key center at 10,0.7 gnuplot replot 把图例的 title 和图线示例调换位置 gnuplot set key reverse gnuplot replot 调整图例边框宽度 width (或高度 height ) gnuplot set key width 1 gnuplot replot 调整 title 文字对齐方式( Left 或者 Right ,注意首字母大写) gnuplot set key Left gnuplot replot 调整图例行间隔 gnuplot set key spacing 1.2 gnuplot replot 调整图线示例长度 gnuplot set key samplen 2 gnuplot replot 这些并不是 set key 的全部参数。在 gnuplot 里,如果想深入了解任何命令的详细用法,不要忘记使用 help 命令。
我们现在所有绘图的坐标刻度均标在图像边框上,无论上下左右。这样做的好处是函数或数据图线清楚,不会和坐标标注混在一起。其实,我们小时候数学课上最早学习坐标系的时候,都是让 X 轴和 Y 轴正交于原点,而刻度标注在坐标轴上。这样的图像在定性表现函数关系,尤其有一定对称性的函数关系时,比较一目了然。 让我们来看看怎样用 gnuplot 得到这样的效果。 用 unset border 命令把边框去掉; 用 set zeroaxis 命令画出正交于原点的坐标轴; 在设定坐标刻度时加上 axis 参数,这样刻度会出现在坐标轴上面,而不是边框上。 为了避免审美疲劳,这次我们拿高斯函数举个例子: gnuplot set term wxt enhanced font "Times New Roman,16" gnuplot gauss(x) = exp(-pi*x*x) gnuplot set title "函数 e^{-πx^2}" gnuplot set samples 500 gnuplot set xrange gnuplot set yrange gnuplot unset key gnuplot unset border gnuplot set zeroaxis lt -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}" offset 12,-5 gnuplot set xtics axis -2,1,2 offset 0.4,0 gnuplot set ytics axis 0,1,1 offset 0,0.4 gnuplot set arrow 1 from 2,0 to 3.2,0 filled size 0.2,15,60 lw 2 gnuplot set arrow 2 from 0,1 to 0,1.22 filled 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 参数控制。
有了坐标系的知识打底,其他很多东西很好谈了。我们的图上除了标签之外,还有一个常用的标志:箭头。关于箭头的命令是 set arrow ,语法和 label 有些类似,包括以下这些常用参数: from ... to ... 箭头的起点和终点坐标。如果把 to 换成 rto ,第二个坐标就表示相对位置而不是绝对坐标。 nohead, head, backhead, heads 分别表示:没有箭头(其实就是线段),箭头在终点,箭头在起点,双向都有箭头。 size length,angle,backangle 箭头尺寸,默认长度单位为 first 坐标单位长度。 下图中 A,B,C 分别代表 length , angle , backangle 。 filled, empty, nofilled 箭头的三种填充风格: 下面我们看例子,还是画 sinc(x) 函数: gnuplot set term wxt font "DejaVu Sans,12" gnuplot sinc(x) = sin(pi*x)/(pi*x) gnuplot set xlabel "X" gnuplot set ylabel "Y" gnuplot set yrange gnuplot set title "sinc(x) 函数" gnuplot unset key gnuplot set samples 500 gnuplot set arrow 1 from 2,1.05 to 0.3,1 filled size 0.5,15,60 lw 2 gnuplot set label 1 at 0,1 point pt 7 ps 1.5 lc rgb "#F87217" gnuplot set label 2 "最大值在(0, 1)" at 2.1,1.05 gnuplot plot sinc(x) lw 2
我们现在知道了 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(pi*x)/(pi*x) gnuplot set xlabel "X" gnuplot set ylabel "Y" gnuplot unset key gnuplot set samples 500 gnuplot set xrange gnuplot set xtics 1 gnuplot set x2range gnuplot set x2tics 1 gnuplot set y2range gnuplot set y2tics 1 gnuplot set grid gnuplot set label 1 "Hello first" 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 left" at 2,0.4 left textcolor rgb "#FF0000" gnuplot set label 2 "Hello green center" at 2,0.5 center textcolor rgb "#00FF00" gnuplot set label 3 "Hello blue right" at 2,0.6 right textcolor 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 lc rgb "#FF9900" gnuplot replot
这次讲讲怎样把图片输出为 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 gnuplot set xtics 1,1,12 gnuplot set term pdfcairo lw 2 font "Times New Roman,8" gnuplot set output "precipitation.pdf" gnuplot plot "precipitation.dat" u 1:2 w lp pt 5 title "北京", "precipitation.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 "precipitation.png" gnuplot replot gnuplot set output gnuplot set term wxt 基于和上面同样的原因,这里使用的 terminal 是 pngcairo 而不是简单的 png ,而字体是 AR PL UKai CN (文鼎简中楷)。下面是生成的 png 图片: