以往通过 GMT4 绘制动图,都是通过生成图片,再将图片转为动图 (eg. convert)。每个图片是动图的一帧;GMT6 现代模式制作动图的理念也基于此。但有两个优势:(1)将背景(前景)和变化的中间图层分开;背景(前景)是静态的,只需固定的脚本;中间图层是动态的,脚本需要和变量联系。如此可以缩短脚本,节省资源。(2)无需复杂的外部命令再处理,利用 movie 几乎可以实现所有要求。本博客通过翻译官方的 movie 文档,简单介绍其用法。

1. 主要用法

movie, 用来创建动图和动画的 GMT6 现代模式下命令。基本语法为:

gmt movie mainscript -Ccanvas -Nprefix -Tnframes|timefile[+pwidth][+sfirst][+w] 
[ -A[+l[n]][+sstride] ] [ -Ddisplayrate ] [ -Fformat[+ooptions]] [ -Gfill] [ -Hfactor] 
[ -Iincludefile ] [ -Llabelinfo ] [ -M[frame],[format] ] [ -Q[s] ] [ -Sbbackgroundscript ]
[ -Sfforegroundscript ] [ -V[level] ] [ -Z ] [ -Wworkdir ] [ -x[[-]n] ] [ --PAR=value ]

movie 模块可产生 GMT 动画,用一个脚本绘制重复出现的背景框架,主程序绘制变化的元素。此模块简化(隐藏)了绘制动画的工作。用户可以聚焦于构建动态的中间图层,而背景框架的绘制会平行执行。组合成动图的帧,会由 PS 文件转为 PNG 图件,最后再合并为动图。对于不透明的 PNG 图,可以通过 -G 选项指定背景颜色。

必选选项:

mainscript

主程序,绘制中间层的 GMT 现代模式脚本(名)。此脚本可通过帧的序号等与动图的变量进行对应,
可以是 .sh, .bash, .csh 或者 .bat 脚本。GMT 通过文件的拓展名识别脚本语言,
同时,以相同的语言创建隐藏的 movie 脚本。

-C

指定画布大小。可选择设定好的画布名或者自定义。设定的画布名有 16:9,和 4:3 两种,
比如 -C4320p, -CCVD 等。自定义尺寸的格式为<width>[<unit>]x<height>[<unit>]x<dpu> ,
例如 15cx10cx50, 6ix6ix100 等。

-N

设置动画的名字,以及设置临时存放帧图的子文件夹。

-T

设置帧的数目,或者提供包含帧信息的文件,文件中每个帧的信息占一行,
列的信息将会通过比变量 MOVIE_COL0, MOVIE_COL1 等提供给主程序。
加 +w 将尾随字符串分隔成单个单词,以方便可以和变量,
例如 MOVIE_WORD0, MOVIE_WORD1 等联系。 框架序号从 0 开始,
可以通过 +s 改变。+p 选项设置框架名标签的长度。

可选选项:

-A 生成 GIF 文件安,加 +l 设置动图循环次数,默认无限循环。
   加 -F 可继续选择组成动图的帧的数量。

-D 设置动图的展示速率(每秒)。

-F 生成 video 的格式,可重复选择;支持 mp4, webm。

-G 框架的背景色。

-H 增减分辨率。

-I 给脚本增加常量。

-L 自动添加标签。

-M 选取图片的一帧作为封面,格式为 -M[frame_number],[format]。

-Q 排错。

-S 指定绘制静态底图或者前景图的脚本名。-b 指定底图名, 
   -f 指定前景图名。

-V 控制信息输出。

-W 默认临时存放文件的文件夹与动画名字相同,由 -N 控制。
   可通过 -W 更改文件夹名字。 

-Z 清除掉临时存放文件的文件夹。

关于 movie 命令用到的参数:

这些参数在脚本可分为两类:常量变量(跟随帧序号);常量可被任何程序获取,包括 MOVIE_WIDTH: 画布宽度; MOVIE_HEIGHT: 画布高度, MOVIE_DPU: 画布精度大小, MOVIE_RATE: 动图每秒钟的展示速率, MOVIE_NFRAMES: 总框架数目。以及 -I 选项提供的数字。变量与帧计数器有关。MOVIE_FRAME: 当前帧的序号, MOVIE_TAG: 帧的标签, 和 MOVIE_NAME: 帧的名字。如果 -T 选项框架信息的文件, MOVIE_COL0, MOVIE_COL1 等同样有效,每列产生一个变量。

2. 示例-制作动画

https://docs.generic-mapping-tools.org/6.1/gallery.html 上有大量例子展示 movie 绘制的动画(视频)和动图(图片)。

这里是我绘制动图的 csh 脚本:

#/bin/csh

rm -rf test
############### background plotting 
cat << EOF > pre.csh
gmt begin
  set lonmin = -50
  set lonmax = 150
  set latmin = 35
  set latmax = 90
  set window = 1    # silde window
  set size   = X8c/3.5c
  
  gmt set FONT_ANNOT_PRIMARY = 8p
  gmt set MAP_TICK_LENGTH    = -0.1c
  gmt set FONT_LABEL         = 10p
  gmt set MAP_FRAME_TYPE     = PLAIN
  
  gmt basemap -R\$lonmin/\$lonmax/\$latmin/\$latmax -J\$size -Bxa50f25+l"Time (s)" \
  -Bya10f5+l"Epicentral distance (\260)" -BSWne -X1.5c -Y10c
  cp ../EU_0.5-2.0_Rspeed_and_local_animation/*.sac .
  gmt sac *.sac -Ed -M1.5/0 -W0p,gray40 -T+s-131
EOF
cat simpleModCurves.gmt >> pre.csh

cat << EOF >> pre.csh
  gmt coast -R102/106.5/29.8/33.8 -JM6c -Ggray -Y-8c -X0.5c -Ba1f0.5 -BWSne
  makecpt -Ctemperature -T0/1/0.001 > topo.cpt
  gmt colorbar -Bxa0.2f0.1 -By+l"Energy" -Ctopo.cpt -DjMR+o-1.2c/0c+w4c/0.15c
gmt end
EOF

############## main script

cat << EOF > main.csh
gmt begin
  set lonmin = -50
  set lonmax = 150
  set latmin = 35
  set latmax = 90
  set window = 1    # silde window
  set size   = X8c/3.5c
  
  echo \${MOVIE_FRAME} \${MOVIE_NFRAMES}
  echo \${MOVIE_FRAME} | awk '{print \$1 * '\$window' + '\$lonmin',0  }' >  tmp
  echo \${MOVIE_FRAME} | awk '{print \$1 * '\$window' + '\$lonmin',180}' >> tmp
  cat tmp | gmt plot -W1p,blue -R\$lonmin/\$lonmax/\$latmin/\$latmax -J\$size -X1.5c -Y10c
  
  set fortfile = \`echo \${MOVIE_FRAME} | awk '{printf "fort.%03d", \$1 + 11}'\`
  echo \${MOVIE_FRAME} | awk '{print 104.25,33.3,\$1 * '\$window' + '\$lonmin'" s"}' | \
  gmt text -F+f12p,7,blue+jBC -R102/106.5/29.8/33.8 -JM6c -X0.5c -Y-8c
  cp ../../EU_0.5-2.0_Rspeed_and_local_animation/\$fortfile .
  awk '{print \$2,\$1,(\$3^1)*1.0}' \$fortfile | gmt plot -Ctopo.cpt -Ss0.1i
gmt end
EOF

############## foregroundscript script

cat << EOF > after.csh
gmt begin
  echo 103.364 30.986 | gmt plot -Sa0.5c -Gblack -R102/106.5/29.8/33.8 -JM6c -X2c -Y2c
gmt end
EOF

############## Generate animation
gmt movie main.csh -Sbpre.csh -Sfafter.csh -C11cx15cx50 -T200 -D5 -Z -Ntest -A+l

上面内容产生三个脚本,第一个脚本 pre.csh,用来绘制波形分布以及海岸线和色标尺,包含了所有不变的要素。第二个脚本 main.csh,在设计当中与第一个脚本的范围大小,都必须一一对应,利用 MOVIE_FRAME 这个变量再通过简单计算与原始数据相联系。第三个脚本 after.csh,用来绘制前景图,也是不变的要素,但如果通过第一个脚本绘制,会被 main.csh 绘制的要素所遮挡,这儿用来绘制地图当中黑色的五角星。

最后一行是最终的 movie 命令; main.csh 就是上面语法中的 mainscript, 再分别通过 -Sb, -Sf 指定绘制背景和前景的脚本,画布尺寸和大小由 -C 选项控制,尺寸要大于脚本中 -J 选项给定的尺寸; -T 给定帧的数量。

3. 示例-制作快照

快照 (snapshot) ,将动图的部分帧排列起来,方便帧之间比较。借助 movie 命令生成 png 图片,再用 subplot 命令和 grdimage 绘制子图:

#/bin/csh

rm -rf test   
cat << EOF > pre.csh
gmt begin
  gmt set FONT_ANNOT_PRIMARY = 8p
  gmt set MAP_TICK_LENGTH    = -0.1c
  gmt set FONT_LABEL         = 10p
  gmt set MAP_FRAME_TYPE     = PLAIN

  gmt coast -R102/106.5/29.8/33.8 -JM6c -Ggray -Y1c -X1c -Ba1f0.5 -BWSne
  makecpt -Ctemperature -T0/1/0.001 > topo.cpt
  gmt colorbar -Bxa0.2f0.1 -By+l"Energy" -Ctopo.cpt -DjMR+o-1.2c/0c+w4c/0.15c
gmt end
EOF    
##############   
cat << EOF > main.csh
gmt begin
  echo \${MOVIE_FRAME} \${MOVIE_NFRAMES}
  set window = 5
  set lonmin = -50
  set fortfile = \`echo \${MOVIE_FRAME} | awk '{printf "fort.%03d", \$1 + 11}'\`
  echo \${MOVIE_FRAME} | awk '{print 104.25,33.3,\$1 * '\$window' + '\$lonmin'" s"}' | \
  gmt text -F+f12p,7,blue+jBC -R102/106.5/29.8/33.8 -JM6c -X1c -Y1c
  cp ../../../EU_0.5-2.0_Rspeed_and_local_animation/\$fortfile .
  awk '{print \$2,\$1,(\$3^1)*1.0}' \$fortfile | gmt plot -Ctopo.cpt -Ss0.1i
gmt end
EOF
##############    
cat << EOF > after.csh
gmt begin
  echo 103.364 30.986 | gmt plot -Sa0.5c -Gblack -R102/106.5/29.8/33.8 -JM6c -X2c -Y2c
gmt end
EOF
##############  
set num = 40    
gmt movie main.csh -Sbpre.csh -Sfafter.csh -C10cx8cx50 -T$num -D3 -Ntest -A+l    
##############
cd ./test/
gmt begin snapshot_test pdf
  gmt set MAP_FRAME_TYPE plain MAP_FRAME_PEN white
  gmt subplot begin 8x5 -Fs10c/8c -M0.2c/0.1c -Ba0
    @ i = 0
    foreach pngfile (`ls test*.png`)
      echo $i $pngfile
      gmt subplot set
      gmt grdimage $pngfile         
      @ i++
    end
  gmt subplot end
gmt end show

前面的命令与上述绘制动图的命令差不多,最后几行用来绘制快照(subplot -Fs 选项应与 movie -C 选项的参数对应):

test_2.gif

snapshot_test.png

4. 其他

参考资料:

GMT movie 官方文档: https://docs.generic-mapping-tools.org/6.0/movie.html

GMT 中文手册: https://docs.gmt-china.org/6.0/gallery/animation/