Generic Mapping Tools(GMT)是科研人员常用的绘图工具。GMT具有强大的功能和一些内置的统计模块。与其他常用的绘图工具(或具有绘图功能的软件,如MATLAB、python、R等)相比,GMT的特点是绘图效率高,但没有可操作的直观界面(GUI)。 我在本系列文章中的文章基于“打开袋子即可食用”的概念,并直接从示例开始。我还将提到gmt4、5和6之间的一些差异。在本文中,我将提前给出示例代码。至于如何从一个例子中推断,请根据GMT手册学习。 前言:GMT使用环境 (1) 装置 我个人使用MAC作为我的工作计算机环境,因此我可以简单地使用诸如自制和macport之类的工具安装GMT。在终端中输入: brew install gmt 或 brew install gmt@5 请注意,自制的GMT软件包是gmt6的版本。如果要安装gmt5版本,需要使用第二个命令。 (2) 使用 通常,GMT代码需要在批处理文档(如bash)中编写。 例如,此实例中使用的代码可以写入plscatter.sh等文件,然后通过以下命令执行。 sh plscatter.sh 正文:(1)散点图+拟合-这是gmt5版本 先上效果图(数据是我随手选的)。 这张图上,包含了大部分GMT画散点图所需要用到内容: 绘制子图 根据数据绘制点并着色。 绘制颜色尺度 添加不同字体、颜色的文本和绘制文本框 上下标等小功能
2 G P* W3 q& V) K1 i* |
伸手党可以直接复制走。如果想学习,则可以继续往后看。 首先,作为bash script文件,文件头必不可少。之后的部分,#之后是注释,不会参与执行。 #!/bin/bash然后,进入一般设置部分。 我这里针对页面和边框等进行了以下设置: - \* T4 T% A+ {) t. M' i
以上可以保存在某一个公用文件(如gmtpar.sh)中,使用时调用即可。 . ./gmtpar.sh 之后,进入具体画图设置。由于bash提供了参数赋值功能,因此将某些设置内容写成参数,这样可以方便同一调控和修改和参照。 range=1800/2400/1800/2400 x、y轴的绘制范围格式为 xmin/xmax/ymin/ymaxcptfile=compare.cpt 颜色盘文件名size=2.8 每张子图大小为2.8 (因为之前设置,这里不加单位,默认为英寸)
]2 P: L4 I* a! }- Pxanot=a200f100g300 x轴每隔200作为主刻度,每隔100为副刻度,每隔300画背景线(图中央交叉灰线)yanot=a200f100g300 y轴每隔200作为主刻度,每隔100为副刻度,每隔300画背景线(图中央交叉灰线)in=sample.txt 这是输入文件,内容大概如下:$ V& U' D0 m: ?- Y7 U
------------------参考:sample.txt内容---------------------# depth Sample1_OBS Sample1_model Sample2_OBS Sample2_model
7 D; e2 o# f3 H8 n' J" i8 m 14.99 2262.00 2061.40 2274.55 2100.88
# Q; p& K9 H6 J( A9 Q 34.88 2287.70 2087.80 2297.18 2117.827 e' v+ U1 r" R6 a8 i
54.36 2296.70 2150.90 2313.25 2152.177 J3 [ H- J. G# @& W/ _$ K9 T
78.84 2288.50 2177.80 2302.91 2150.53
0 J0 l( J' F) p8 m6 G" K-----------------------sample.txt内容-----------------------out=sample.ps 这是原始输出文件,为postscript格式(最后我用psconvert转换为了jpg格式)以上对实际用途的基本设置完成。大家可以看出,这里主要是设置了图的大小、范围、坐标轴、输入和输出的文件名。紧接着,我们就开始正式画图了。 绘图第一步:确定图的样式
4 V/ q2 w; X T6 t! A% G t
根据上面给出的sample.txt的内容和格式,我们需要在XY平面上绘制两个不同样本的三个信息(深度、观测值和模拟值)。同时,面对此类数据,我们一般需要观察对比模拟值是否接近观测值,以及不同深度是否对其产生影响。因此,我们可以使用散点图来验证我们的模拟值可以接近观测值,并分别与观测和模拟的X和Y坐标一一对应。理想情况下,模拟值应等于观测值,即满足y=X的函数。我们选择使用颜色表示深度,这不会破坏y=X的对应关系,但也会看到深度的影响。 因为有两种样本并共享深度信息,所以可以清楚地得出结论,需要绘制两个子图并使用相同的颜色比例。 绘图第二步:指定颜色
: B' D4 A3 s8 } gmt makecpt -Cseis -T0/60/2 -D -I > $cptfile-C: 使用seis基准颜色盘设置 -T: 颜色对应的最小值为0,最大值60,间隔为2 -I:颠倒seis基准的最大最小值代表的颜色 -D:如果数据超过上面设置的最大最小值,则用前景和背景色代替 绘图第三步:绘制第一子图(panel1)的底图 8 }9 L4 }" i! g: a- c H
我这里根据命令和选项,加了注释,方便大家理解。部分参数(如range等)在上面已经进行了设置。 ########panel 1gmt psbasemap -R${range} -JX${size} -B${xanot}:"Sample 1 Obs. [m@+2@+]":/${yanot}:"Sample 1 Model [m@+2@+]":WSne -X1 -K > $out选项表示意思: psbasemap: 底图命令 -R: 指定范围 -J: 底图类型 -B: 轴设置,并标注文字。 这里为了表示平方米,用了上标。 两个@+ @+中间的内容即为上标 。 -B选项后的WSne:轴标注仅在大写的W(左)S(下)出现,小写表示n(上)和e(右)只画线不标注。WSNE中任意一个不写,则对应方向不画线也不标注。 -X1: 图的起始点横向移动1英寸,这是根据图的数量和大小调整的,可以自行更改。GMT6开始因为纸张无限大,一般无需设置。 -K :下方还有命令,不要结束 > : 一个大于号表示新建并输出到文件,类似地>>表示不新建而是追加输入。 绘图第四步:绘制带颜色的点
3 S! D9 K Y. z8 h 读取输入文件,并逐行读取。如果满足条件的话,取输出第2列、第四列、第一列 这里的竖线表示下面一行接上$ D: j8 E# l% c, z) t8 I
awk '{if ( $1 != "#" && $2 > -900. && $4 > -900. ) print $2,$4,$1}' $in |绘制点2 L5 M; r2 g0 i
gmt psxy -R -J -Sc0.04 -C$cptfile -O -K >> $out这里我用到了awk命令,主要是为了增加if条件判断。 上文条件的意思是:第一列不是“#”号,且第二列和第四列都大于-900。 增加这一条是为了防止读取空值或是读取第一行的注释,造成不必要的麻烦。 && 表示if语句中的【并且】(and) psxy:用于绘制点线面等 -Sc:绘制图样、用c表示绘制圆(circle)、0.04表示圆的直径为0.04(英寸) -R和-J:和之前一样。这里因为没有更改,所以可以省略具体内容。 -C:使用颜色文件 -O:追加到已有的ps文件中 绘图第五步:拟合直线并绘出 m( P- X# {$ k
利用了GMT内置的线性拟合功能,拟合出了一条直线(1700<x<2500,间隔1)并输出。这稍微有点进阶,具体可以参加GMT的手册。 这里的psxy,没有添加-S选项,则默认是画线。 -W0.5:线的粗细为0.5 绘图第六步:图中添加文字 ) U8 y# x0 W- Z) u9 H6 s$ \& H: L
gmt pstext -R -J -N -F+a0+f14p,Helvetica-Bold+jLT -O -K >> $out << EOF1850 2350 a)EOFgmt pstext -R -J -N -F+a0+f12p,Times-Italic+jLT -Gwhite -Wthinner -O -K >> $out << EOF2000 1900 @;blue;y = 0.791 x + 481.469@;; 3 m+ N a- { z% t a" o
EOFpstext:添加文字 -F:设置文字角度(a)为0,大小(f)为14,字体Helvetica-Bold,基准锚点为左(L)上(T) << EOF: 常见的bash命令,与GMT无关。本行命令使用到出现EOF为止的内容。 -N:表示如果坐标超出底图范围,也依然绘制 1850 2350 a): 前俩数字分别表示x,y坐标。 'a)' 是书写内容。 -G: 文本框底色 -W:文本框边框粗细 这里有一个进阶颜色用法。通常,文字的颜色是在-F中设置。 但是如果想要在一次输出中,出现多种颜色,就需要用到GMT5引入的颜色调用命令 @;【颜色】;【输出内容】@;; 【颜色】:格式多种多样,red, blue, green等是内建的,也可以用RGB值,比如蓝色是0/0/255 注意:这些@和分号都要保留。 例子中是GMT5的格式,GMT4可以参考下面: #For GMT4gmt pstext -R -J -N -O -K >> $out << EOF1850 2350 14 0 2 LT a)EOFgmt pstext -R -J -N -W0.5 -Gblue -O -K >> $out << EOF2000 1900 12 0 6 y = 0.791 x + 481.469EOF绘图第七步:子图2 3 D. b7 P' r7 X( Z
GMT5中的子图,是通过追加绘制和移动来实现的。 gmt psbasemap -R${range} -JX${size} -B${xanot}:"@~D@~Sample 2@-Obs.@- [m@+-2@+]":/${yanot}:"@~D@~Sample 2@-model@- [m@+-2@+]":WSne -X4 -O -K >> $out类似子图1,但是我这里使用了 -O表示追加,并且用了两个大于号>> 这里,我用到了希腊字母 。 在GMT中,特殊符号需要用到@~@~。其中,@~D@~是大写的Delta,类似地@~d@~是小写的delta: 。
$ B- W( r- m& ?( i- R/ ^# C此外,我也给出了下标的用法:@-@- (参考上标是@+@+)。 之后的内容,和子图1类似。 注:GMT6有更简单的子图绘制方式,在之后的文章中会提到,此处略过不表。 绘图第八步:绘制colorbar , u) g3 i( S' w0 E" s _
gmt psscale -R -J -DJMR+v+ef -C${cptfile} -Bx+l"Depth" -By+l"m" -Np -B20 -O >> $outpsscale 绘制颜色色条 -D:设定位置和样式。其中子选项J之后的MR表示在图右侧(R)中间(M)的位置,v表示vertical(竖)。e表示在前景(f)方向增加小三角。 注:因为我在makecpt时用了-D选项。输入的深度数据最小值也不比0小,而最大值则超过了60,因此我仅在60处加了三角。 -C: 颜色基准文件。应与之前使用的文件相同 -B:设置颜色色条的间隔,标记。 -Bx是设定色条的x轴,-By是设定色条的y轴。l子选项表示添加标注文字。-Np是让色条按照间隔,每个颜色输出为方形色块(需细看),而非连续变化的色条。-B20表示色条轴数字值的间隔为20,实例中就是0,20,40和60。 注:-Bx,-By可以分开设置。 绘图第九步:转换格式
& v& @# _2 O! I" V' N$ m9 I- g gmt psconvert -A0.3c -P -E600 -Tj $outecho Output : $outrm $out在不同的场合,我们需要不同的图片格式,并不是所有的计算机都能打开PostScript(PS)格式的文件。因此,GMT还提供格式转换功能。这里,GMT可以通过命令来裁剪图中的空白区域。 答:意指控制图片的大小并切断空白区域。0.3C表示切割边缘与每个底图之间的距离,单位为cm(c)。这里的底图不包括颜色栏和轴比例编号,因此需要小心处理。 -P:强制门户模式。 -E:图片分辨率(单位:PPI)。由于PS格式是矢量格式,没有分辨率的概念,因此有必要指定转换图片的分辨率。一般来说,提交线图的分辨率PPI大于1000,而其他图片的分辨率约为300-600。您还可以将其转换为PDF格式,以避免图片模糊。 -T:转换格式。常用的有J(JPEG)、P(PDF)、t(TIFF)等。 最后,我用echo输出文件名并删除原始PS文件,只留下转换后的JPEG文件。 以上就是绘制一幅散点图所需要的所有步骤。 个人体验,GMT绘图较Python,Matlab等,绘制的速度会快一些。以此图为例的时间如下,图中每个子图有大概4000个点,并且还包括了格式转换的时间。 但是由于没有GUI,每次绘制需要一步一步的对图片内容,标注位置等进行调整。比如,为了生成此图,我大概进行了10分钟左右的修改和调整。 当然,努力工作的结果是有目共睹的。绘制的图片非常漂亮,非常适合学术报告、海报印刷和期刊投稿。自从我获得硕士学位以来,我一直在使用gmt4。我还使用了MATLAB、Python和originpro的绘图功能,但由于绘图的习惯和统一性,我回到了GMT。最近,它经历了从gmt4到gmt5再到gmt6的自我更新和升级。我一时兴起,用GMT写了一些常用的句子,希望能帮助和启发想要或正在使用GMT的学生。当然,我的代码不一定是最佳的解决方案,欢迎您进行更正。
% M8 E8 p6 m* S$ d \' E |