gnuplot : Pythonスクリプトにパラメーターを与えてプロット(sprintf)
はじめに
前回の解説記事で、gnuplotからPythonスクリプトを呼び出し、その出力をPiped-dataでプロットする方法を取り上げました。このときは単に用意したデータをプロットするだけでしたが、今回はそこから発展してPythonスクリプトにパラメーター、つまり引数を与えてプロットする方法を解説します。これによりPythonスクリプトの出力結果をgnuplot側から操作することが可能となります。
Pythonスクリプトでパラメーターを与えてプロットする方法
準備 : Pythonスクリプトで引数を受け付けるようにする
まず用いるPythonスクリプト自体を引数を受け付けるように作っておく必要があります。ここでPythonについて解説はしませんが、簡単に言うと"sysモジュール"の"argv"を用いて作ります。例えば、"test01.py"というPythonのスクリプトファイルを以下のコード内容で作ります。
import sys
a = sys.argv[1]
print(a)
このコードを実行するときに以下のように"1234"という引数を与えると、その引数が出力されます。
$ python3 test01.py 1234
argvはリストとなっていて、argv[0]にスクリプトファイル名、それ以降に引数が格納されます。
gnuplotから呼び出す方法 - その1: 直接Piped-dataのところに記述する
gnuplotから引数を与えてPythonスクリプトを呼び出すとき、最も簡単には次のようにそのままPiped-dataのところに記述してしまえばよいです。gnuplot> plot "< python3 test01.py 1234" with linespoints
gnuplotから呼び出す方法 - その2:sprintfで引数を変数から読み込む
ある変数、例えば"a = 321"を用意して、それを引数として用いることを考えます。gnuplotには文字列関数としてsprintfがあり、この関数では与えられた値を指定されたフォーマット内に挿入した文字列で得ることが出来ます。例えば
a = 321
print sprintf("variable test : a = %d", a)
として実行すると
variable test : a = 321
という文字列が出力されます。
(%dは整数を出力する指定子で、ここは値によって適宜変更する必要があります)
これをPiped-dataの記述に用いるとこのような書き方となります。
gnuplot> plot sprintf("< python3 test01.py %d", a) with linespoints
応用編
ループ処理に組み込む
上の方法その2を用いるとgnuplot側で変数として引数を扱えるため、ループ処理に組み込むことでPythonスクリプトに与える引数を連続的に変えることが出来るようになります。例えば、以下のGIFアニメはPythonスクリプト内でデータを作成する際に乱数を与えて徐々に誤差を大きくしていくというもの。
ループ処理を用いたこのグラフのソースコードを次に載せておきます。
ちょっとしたコツですが、gnuplotとpythonの両方のスクリプト処理を書いていく必要があるので、なるべく混乱しないようgnuplotの方では処理はなるべく簡略化した方がいいでしょう。
gnuplot側のソースコード
set yrange [-10:10]
s = 0
while (s < 250) {
set label 1 sprintf("s = %d", s) center at screen 0.5, 0.3 font ",20"
plot sprintf("< python3 script03_01.py %d", s) w p ps 0.5 pt 6 lc 'red',\
sprintf("< python3 script03_01.py %d", 0) w l lc 'gray'
s = s + 1
pause 0.01
}
python側のソースコード(script03_01.py)
import math, random, sys
s = float(sys.argv[1])
list_tmp = []
list01 = []
data_length = 100
for i in range(data_length):
list_tmp = [i, math.sin(math.radians(i*10))+random.uniform(-0.1,0.1)*s/10.0]
list01.append(list_tmp)
for j in range(data_length):
print(list01[j][0], "{:.3f}".format(list01[j][1]))
gnuplot関連のブログ記事
コメント
コメントを投稿