# 津波計算結果の可視化
## 概要
津波計算結果のスナップショットを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`