# 津波計算結果の可視化 ## 概要 津波計算結果のスナップショットをPython,FFmpegを用いて,2次元可視化を行います. メインはPythonによる作画の仕方で,FFmpegは基本的なコマンドのみなのですぐ終わります. 両方ともインストール済みの前提で話を進めるので,入れといてください. 出来上がる動画は以下のようなものになります. ## 手順 1.PythonによるPNGファイルの作成  2.FFmpegによる動画作成 ## PythonによるPNGファイルの作成 とりあえずコードは以下の通り. 説明は後からします. ```python= # モジュールのインポート import numpy as np import matplotlib.pyplot as plt import matplotlib.cm as cm import glob import copy # # 地形データの読み込み data_bath = np.loadtxt('bathymetry/region1.dat',dtype=float) bath = data_bath[::-1] # # 津波スナップのリスト取得 tsunamilist=glob.glob('tsunami/snap1*') tsunamilist.sort() # # 津波スナップの間隔 dt = 0.1 ts = 300 # # 作図 for filename in tsunamilist: # 画像タイトルの設定 title = filename.split('snap1') title = title[1].split('.') title = title[0] # # スナップ時間の設定[s] title_int = int(title)*dt*ts # print('now processing : '+ title) # # 水位データの読み込み data_tnm = np.loadtxt(filename,dtype=float) tnm = data_tnm[::-1] # 非浸水部分の透過 tnm = np.ma.masked_where(tnm == -99.0, tnm) # # 図の設定 plt.figure(figsize=(8,10)) plt.xlim(0,749) #originally 750 plt.ylim(0,999) #originally 1000 plt.tick_params(labelleft='off',labelbottom='off') # # 地形の作図 cmap1 = copy.copy(cm.Greys) bathymetry = plt.imshow(bath, cmap=cmap1, vmin=-100000, vmax=70000) # # 水位の作図 cmap2 = copy.copy(cm.RdBu_r) tsunami = plt.imshow(tnm,cmap=cmap2,vmin=-5,vmax=5) # # 水位のカラーバー plt.colorbar(tsunami, cmap=cmap2, aspect=30, shrink=0.7, extend='both', \ ticks=np.arange(-5.0,5.1,2.5), label = 'Water level [m]') # # 時間の描画 plt.title('Elapsed time : '+str(title_int)+' [s]') # # 図の保存 plt.savefig('./snaps/' + title + '.png',dpi=100) plt.close() ``` - モジュールのインポート コードに示したのは必要最低限のモジュールたちです. したいことが増えたらその都度増やしてください. 場合によっては`pyplot`の前に以下を付け加える必要があります(詳細は調べて). ```python= import matplotlib as mpl mpl.use('Agg') ``` - 地形データの読み込み `np.loadtxt`を使ってデータの読み込みをします.値は実数なので`float`にします. 左下を(0.0)にするために-1をつけます. `np.loadtxt`はきれいな配列になっていないと読み込まないので,気を付けてください. - 津波スナップのリストの取得 `glob`を使って津波スナップのファイルの名前を取得し,リストにします. 念のためソートしてますが,別にしなくてもいいです. `glob`は指定したパスにターゲットがあればとってきますが,なくても特にエラーにならないので,パスは間違わないように. - 津波スナップの設定 津波計算で設定した,`dt`と`time_step`を記述しますが,コードによっては不要です. - 作図 津波のスナップファイルは複数あるので,ループさせます. ループ変数`filename`に`tsunamilist`をいれるとわかりやすいので,そうしてます. - 画像タイトルの設定 スナップファイルの名前にはスナップ時間の情報が入ってます. その時間部分だけを取り出して,`title`に入れます. `filename`には`tsunami/snap10000.dat`が入っており,この操作を行うことで`title`に`0000`が入ります. - スナップ時間の設定 `title`に`dt`と`ts`を掛けた値がスナップの時間だったので,行った操作です. 計算コードによっては行う必要ありません. - 水位データの読み込み ここでやっとスナップの水位データを読み込みます.やり方は地形データと一緒です. - 非浸水部分の透過 スナップの水位データには水のない部分(陸)は適当な値が入っていて,透過させる必要があります. 僕のコードでは`-99` が入っているのでそれを透過(マスク)します. 透過条件は`tnm == -99`で,当てはまらない(水がある)部分は`tnm`となるようにします. - 図の設定 さぁ,ここからが作図になります. コードを見やすくするために,先に設定はここで済ませましょう. `Python`のナンバリングは0からなので,メッシュ数は-1する必要があります. 軸の目盛りを消したかったので,`tick_params`を設定してます. - 地形の作図(水位の作図) `plt.imshow`で作図をします. カラーマップを先に決めておき,色の範囲は`vmin,vmax`で指定します. 今回の設定は,地形がグレー単色,水位が押し波が赤,引き波が青になってます. `Zorder`を指定しない場合は,地形を先にしないと水位が移りません. - 水位のカラーバー `plt.colobar`でカラーバーを表示します. `aspect,shrink`でカラーバーの形状を決めます. `extend`でバーの端の形状が変わります.vmin,vmax以上のデータが存在するかどうかで変える必要があります. `ticks`で目盛りの表示する値を決めます. `label`でラベルつけます. バーを水平にしたければ,`orientation='horizontal'`を加えます. - 時間の描画 スナップ時間を`title`として図の上に記述します. 図の中に入れたい場合は`plt.text`で記述すればできます. - 図の保存 最後に図の保存をします.これを忘れると今までの苦労が水の泡です. 最初の因数にファイルネーム,`dpi`は解像度の値で高いほど綺麗で重いファイルになります. 以上を行うことで,pngファイルの完成です. コードは基本しかかいてないので,自分好みにアレンジしてください. 行った改良は他のページに書くように頑張ります. ## FFmpegによる動画作成 最初に言った通り,ここからはすごく簡単かつ速いです. 以下のコマンドが例です. ``` $ ffmpeg -r 4 -i %04d.png -vf format=yuv420p -qmin 1 -q 1 tsunami.mp4 ``` `-r 4` : 動画のレート,1秒間当たりの表示枚数 `-i %04d.png` : 画像ファイルの指定,画像ファイルは連番であり,ピクセル数が(偶数)x(偶数)である必要あり,`%04d`は4桁の数字を表す `-vf format=yuv420p `: 動画のフォーマット,これはよくわからん `-qmin 1 -q 1 `: 動画の綺麗に関するもの,これもよくわからん `tsunami.mp4` : 出力ファイルの名前,拡張子指定もここでする ここには簡単な説明しか書いてない(というかわからない)ので,調べてみてください. 一応これでもできます. ## 完成品 ここまでで示したコードでできたものを以下に示します.こんなのができます.(ちょっとカクカクしてますが) 他のページに僕が行った改良を載せようと思うので,出来てたらそちらも参考にするとよいかと思います. {%youtube j3MLelzNHoM %} ## 追記 - 地形データと津波データの読み取りの際にヘッダーがある時には以下のように`skiprows`をオプションに追加するとできる. ```python np.loadtxt(fliename,dtype=float,skiprows=6) ``` ###### tags : `Python` `FFmpeg` `tsunami`