Gnuplotを使って動画を作ってみよう
(最終更新日:2022/06/20)ここでは、Fortran等を用いた数値計算の実習する際に、gnuplotとImageMagicを使って計算結果から動画を作成する方法を解説します。
以下では、「1. Fortranによる連番ファイルの出力」、「2. gnuplotによる画像ファイルの出力」、「3. ImageMagickによる画像の結合」の3ステップを通じて、数値計算結果を動画として可視化する方法を学びます。
1. Fortranによる連番ファイルの出力
ここでは、まずFortranを使って、連番ファイルを作る方法について学びます。Fortranのdoループを用いると、ファイル名に連続する番号が付けられたファイルの複数用意することが出来ます。例題として、下記のFortranプログラムをコンパイル・実行してみましょう。
program main
implicit none
integer :: Nx,Nt,ix,it
real(8) :: Xf,Tf,dx,dt
real(8) :: f,t,x
character(50) :: cit,filename
Xf=10d0
Tf=10d0
Nt=50
Nx=100
dx=Xf/Nx
dt=Tf/Nt
do it=1,Nt
t=dt*it
write(cit,'(I7.7)')it
filename=trim('anim_')//trim(cit)//'.dat'
! Writing a data file
open(20,file=filename)
do ix=1,Nx
x=dx*ix
f=sin(x-t)
write(20,'(3e16.6E3)')x,f
end do
close(20)
end do
end program main
上記のプログラムをコンパイル・実行するとanim_xxxxxxx.dat
という50個のデータファイルが出力されます。それぞれのデータファイルには、異なる時刻\(t\)に対する関数\(f(x,t)=\sin(x-t)\)の値が座標\(x\)の関数として格納されています。ファイルの第一列目は座標\(x\)の値、第二列目は関数\(f(x,t)=\sin(x-t)\)の値を記録しており、ファイル名に含まれる整数値が時刻\(t\)と関連付けられています。上記のFortranコードは、時間\(t\)に対するdo
ループと座標\(x\)に対するdo
の二重do
ループから成っており、外側のdo it=1,Nt
から始まるdo
ループでは、各ステップでopen(20,file=filename)
によってファイルを開き、そのファイルへ三角関数の情報を書き込んでいます。各ステップのit
について、write(cit,'(I7.7)')it
によって整数型変数it
から文字型変数cit
への変換を行い、カウンターit
の整数を含むようなファイル名をfilename=trim('anim_')//trim(cit)//'.dat'
によって作っています。do ix=1,Nx
から始まる内側のdo
ループでは、三角関数を座標\(x\)の関数としてそれぞれのファイルに書き出しています。
2. gnuplotによる画像ファイルの出力
次に、上記で作られた連番のデータファイルから、gnuplotを用いて連番の画像ファイルを作る方法を解説します。ここでは、gnuplotのwhile
文を用いて、データファイルから画像ファイルへ変換することを考えます。例として、次のようなgnuplotのスクリプトを考えます。このスクリプトをテキストエディタを使ってplot.plt
と名前を付けて保存し、ターミナル上でgnuplot plot.plt
と入力することで、gnuplotにスクリプトを読ませ、スクリプトを実行させることが出来ます。上記で作られた連番ファイルが準備されていれば、下記のgnuplotスクリプトを実行することで50個の画像ファイル(gifファイル)が生成されます。
set term gif
set yrange [-1.0:1.0]
j = 0
while (j<50){
j = j+1
filename_data = "anim_".sprintf('%07.0f.dat', j)
filename_gif = "anim_".sprintf('%07.0f.gif', j)
set output filename_gif
p filename_data u 1:2 w l
unset output
}
ここでは、簡単に上記のgnuplotスクリプトについて解説します。スクリプトは、gnuplotに読ませることで上から順番にコマンドを実行させることが出来ます。先頭のset term gif
は、gif形式の画像ファイルを出力するための出力形式の設定を行っています。次のset yrange [-1.0:1.0]
では、y軸の描画範囲を[-1.0:1.0]の範囲で固定しています。次にj = 0
にてループのカウンターをゼロに初期化し、while
文を用いてそれ以降の処理を繰り返し行っています。ここで、while (j<50){}
は、j
が50よち小さい間だけ、次の操作を繰り返す文となっています。そのすぐ後にj=j+1
によってループのカウンター変数を1増加させ処理を進めていきます。filename_data = "anim_".sprintf('%07.0f.dat', j)
とfilename_gif = "anim_".sprintf('%07.0f.gif', j)
の文では、整数j
文字列に変換し、データファイル(.dat
)と画像ファイル(.gif
)のファイル名に組み込んでいます。その次の、set output filename_gif
では出力するファイルの名前を設定し、さらにp filename_data u 1:2 w l
にてデータファイルから画像ファイルへの出力を行っています。この操作をjを1から50まで繰り返すことで、連番のデータファイルから連番の画像ファイルを作ることが出来ます。
3. ImageMagickによる画像の結合
次に、上記の操作で作られた連番の画像ファイルをImageMagickにより結合することで、動画の作成を行います。まず、ImageMagickがCygwinにインストールされているかを確認するためにコマンドconvert -version
をターミナル上で実行してみます。無事にImageMagickのバージョンが表示されていれば、ImageMagickはCygwinにインストールされています。ImageMagickがインストールされていない場合は、Cygwinのインストールページを参考にImageMagickをインストールしてください。
ImageMagickの準備が整ったら、序機で用意した連番の画像ファイルがあるディレクトリ内でconvert -delay 10 -loop 0 anim_*.gif anim.gif
を実行してみましょう。ここでは、convert
はImageMagickにおけるファイル変換のプログラムであり、anim_*.gif
で表される連番の画像ファイルを結合することでanim.gif
というgifのアニメーションファイルが作成されます。convert
のオプションである-delay
は、連結されたファイルの移り変わる速さを決めるオプションであり、-loop 0
は連結されたgifアニメーションを無限にループすることを表すオプションです。上記の一連の操作によって下に示したようなgifのアニメーションが作成されているはずです。この方法を応用して、数値計算の結果を可視化してみましょう。