雑記 - gnuplot Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

!invalid colorbox option ??
gnuplot 4.2 patch level 3 で保存したファイルを patch level 2 の gnuplot で load すると
gnuplot> load "FL.gnu4

gnuplot> set colorbox vertical origin screen 0.9, 0.2, 0 size screen 0.1, 0.63, 0 front bdefault
                                                                                   ^
          "FL.gnu4", line 141: invalid colorbox option
てな error が。4.2.3 に上げて解決。
patch level 3 で colorbox に front option というのが加わったということかな。

!pause
gnuplot の設定ファイルを引数で渡して図を描画させると、一瞬表示した後に消えてしまう。これを防ぐには設定ファイルの末尾に pause -1 を加えておけばよい。こんなかんじ↓
#!/usr/bin/gnuplot
set term x11
plot sin(x)
pause -1
こうすると terminal で改行を入力するまで表示される。なお、pause の後に正の実数(整数)を書けば、その数秒ほど pause してくれる。

また -persist オプション付きで起動すると改行を入力した後も図は表示され続ける。

!ギリシャ文字と斜体
set ylabel "{/Symbol-Oblique D}({/Italic z}) / {/Symbol-Oblique p} {/Italic T_c}"
のようにして、
set term post eps enhanced "Arial" 24 lw 3 dl 3
みたいにする

!初期設定
~/.gnuplot というテキストファイルの中に設定を書くことで、初期設定可能

!splot
こんな絵が描きたいとき。{{attach_view('hoge.png')}}

次のようなデータを作る。
#  omega,  theta,  n
4.970000e-01 5.050000e+01 1.809472e-02
4.970000e-01 6.917188e+01 2.280921e-02
4.970000e-01 8.387644e+01 2.176572e-02
4.970000e-01 9.304867e+01 1.962956e-02
4.970000e-01 9.759271e+01 3.569119e-02

4.960000e-01 5.050000e+01 1.641266e-02
4.960000e-01 6.917188e+01 2.930498e-02
4.960000e-01 8.387644e+01 2.568140e-02
4.960000e-01 9.304867e+01 1.705182e-02
4.960000e-01 9.759271e+01 2.670954e-02

4.950000e-01 5.050000e+01 1.508653e-02
4.950000e-01 6.917188e+01 4.174454e-02
4.950000e-01 8.387644e+01 3.351103e-02
4.950000e-01 9.304867e+01 1.529229e-02
4.950000e-01 9.759271e+01 2.122146e-02
のような空行で区切ったデータを用意して
set hidden3d
splot "hoge.d" with lines
とすればよい。

!splot と ticslevel
splot で 3d なグラフを描くとデフォルトで z 軸の 0 がシフトする。地に足を付けるには
set ticslevel 0
とすればよい。

!palette
3D なグラフで値によって線の色を変えるのであれば、lc を palette にすればよい。
splot "hoge.d" lc palette

palette の色は set palette で調整できる。(デフォルトは暗いので)たとえば虹色にするなら
set palette rgbformulae 33,13,10

!view (splot の表示角度)
set view 33.0, 35.0
のようにすれば角度を指定できる

!pm3d
カラーマップを用いた 3次元表示するには pm3d をセットすれば良い
set pm3d
splot "hoge3D.d"

x-y 平面に投影するように表示するには
set view map
splot "hoge3D.d" with pm3d
のように

!目盛
手動で目盛を付けたい時
set xtics   ("0" 0.00000, "0.3" 0.300000, "a" 0.650000, "1.0" 1.00000)
のようにすると、x軸の 0.0, 0.3, 0.65 1.0 の位置に目盛を刻んでくれる。また 0.65 の位置には a と表示される。またグリッドを表示するには以下のように
set grid
x軸の目盛を上下に出す場合は mirror を、下にだけ目盛りを出す場合は nomirror を付ければ良い
set xtics mirror     上下に目盛を出す場合
set xtics nomirror   下にのみ目盛を出す場合

!目盛やラベルの文字位置
上記の方法により手動で目盛を付けた際、記述する文字の向きを変えたりや位置をずらすには、 rotate by や offset を用いればよい
set xtics ("0" 0.0, "hogehogehoge" 0.1, .....)
set xtics rotate by 45 offset 0.0,-0.1
set zlabel "hogehoge" rotate by 90
のようにすれば、目盛に付けられる 0 や hogehogehoge という文字を 45 度回転し、(0.0,-0.1) ほどずらした位置に配置できる

!グラフの枠 border
枠を表示するには(default)
set border
枠を非表示にするには
unset border
四方の枠の表示は set border の後に整数を指定。下の枠が 1、左が 2、上が 4、右が 8 といった具合で、例えば x 軸と y 軸のみを表示するなら
set border 3
とすればよい。

!点を打つ
任意の場所に点を打つには label を使う
set label 1 "" point pt 7 ps 2 lc rgb 'red' at 0.2, 0.3
pt 7 は丸い点、ps 2 はサイズ、lc rgb 'red' は色指定

!線を引く
矢尻なし nohead の arrow を使うのが汎用的かな
set arrow 1 from 0.1,0.5 to 0.9,1.2 nohead

!y2軸を使う
y軸だけでなく、y2軸も使うときは次のように axes を指定
set y2tics
plot "hoge.d" using 1:2 axes x1y1, "hoge.d" using 1:3 axes x1y2
set y2tics が無いと、y2軸の目盛(数値)を書いてくれない

!grid
グリッド線を引くには
set grid
これで x軸と y 軸に関して目盛に合わせた grid 線が引かれる

もし、x軸に関して grid 線を引きたくない場合には次のように
set grid noxtics

y2 軸に対して grid を引くには
set grid y2tics

!複数の 2D plot をまとめて 3D plot  (たぶん普通じゃない使い方)
データ形式が  x, y1, y2, y3, y4, y5, ... のようなデータファイル hoge.d があったとき、通常なら
plot "hoge.d" u 1:2, "hoge.d" u 1:3, "hoge.d" u 1:4, "hoge.d" u 1:5, ...
のようにして 2D プロットするが、描かせる線が多い場合、線が重なってしまってよく分からなくなることがある。このような時、各線を一平面上に重ねた 2D プロットするのではなく、各線の様子をみるために別々の平面上にプロットして 3D 的にぐりぐり回して俯瞰できたらいいな、ということがある。
それを splot で実現するための方法について頭を悩ませていたのだけど、簡単な方法をひらめいたのでメモしておく。(見つけてないけど何処かに書いてあるかもしれない。いろいろ調べてみたのだけど、splot についてあれこれ書いている人は少ないみたい。)

結論だけ書くと実はかなり簡単。
  splot "hoge.d" u (1):1:2, "hoge.d" u (2):1:3, "hoge.d" u (3):1:4, "hoge.d" u (4):1:5, ...
splot の場合、(x,y,z) のセットでデータを与えないといけない。using option で : (コロン)で区切った各データ列を与える必要があるわけだ。ここでは、 x 列を線の番号とし、y 列を data x 、z 列を data y1 or y2 or... としたという話。(なんで x 列の数字をカッコで囲んでいるかの説明は書かないよ。分からない人は調べてね。)

あと、 x 列の目盛りに意味がないので、たとえば次のようにして変えておくといいかも。x 列の目盛り自体を書かないというのもありですね。
set xtics ("A" 1.0, "B" 2.0, "C" 3.0, "D" 4.0, ... )

!line type
version 4.6 と 5.x 以降では、線の style の扱いが若干違うらしい。(linetype じゃなくて dashtype で制御するとか terminal option の solid/dashed が無くなったとか。)
ここでは version 4.6 での話。default の線種がどうも気に入らないということで、どの line type を使うか判断するため default 値のメモ
||linetype||線種||色
||1||実線||赤
||2||破線||緑
||3||破線(短)||青
||4||点線||マゼンタ
||5||一点鎖線||シアン
||6||実線||赤
||7||4点||グレー
||8||二点鎖線||橙
||9||2点||黒
||10||一点鎖線(短)||黄
例えば 4 番の色を青色に変更するには
set linetype 4 lc "blue"
の様にする。

なお、モノクロのグラフにする際には、上記のような line color の変更をしない方が良い。line color を変更したら、線種がずれてしまう。(バグっぽいような…)

!line type (補足)
4.6 と 5.x の違いについて、stackoverflow の[[ここ|https://stackoverflow.com/questions/19412382/gnuplot-line-types]] に書かれた内容が分かりやすい。あと日本語であれば [[こちら|http://www.ss.scphys.kyoto-u.ac.jp/person/yonezawa/contents/program/gnuplot/version5.html#color]]とか。

例えば、線の配色については 3つのセットがあるらしい。set colorsequence (set colors) で変えられる。
set colors default              # 5.x 系の配色(color universal design を考慮)
set colors podo                 # color universal design の別配色(Wong (2011) [Nature Methods 8:441])
set colors classic               # 4.6 系の配色

5.x 系になって、配色が universal design を考慮したものになったうえ、 terminal によって色が変わらないようにもなったらしいので、5.x 系に移るべきか。

!文字変数
例えば、hogehogeahoaho1.d みたいな長ったらしい名前のデータファイルを plot するときに
plot "hogehogeahoaho1.d" u 1:2, "hogehogeahoaho1.d" u 1:3, "hogehogeahoaho1.d" u 1:4, ...
のように書くと見にくいし、ファイル名を変えるのも面倒。こんな時は
n="hogehogeahoaho1.d"
と n に代入したのちに、
plot n u 1:2, n u 1:3, n u 1:4, ...
とした方がすっきり。もちろん次のように一行にまとめても良し。
n="hogehogeahoaho.d"; plot n u 1:2, n u 1:3, n u 1:4, ...
これなら、ファイル名変更も一か所だけでラクチン。

!for と sprintf
たくさんのデータファイルを順次表示するとか、繰り返し操作が必要なときの話。繰り返しは for loop を使い、変化する文字列は sprintf を使う。

例えば、 hoge01.d, hoge02.d, hoge03.d,... といったデータファイルがあったとき、それを順次グラフ化するには
do for [i=0:15] {  n=sprintf("hoge%02d.d", i); plot n u 1:2, n u 1:3; pause 3; }
みたいにすればよい。
なお、sprintf で実数を表すなら
s=sprintf("theta= %5.2f pi", (i-51)/100.0);
のように。

!plot ""
ちなみに、同じファイルの異なる列を plot するとき
plot "hoge.d" u 1:2, "hoge.d" u 1:3
と書くかわりに
plot "hoge.d" u 1:2, "" u 1:3
のように略して書くこともできる。(が、上に書いた文字変数を使う方がきれいかな。)

!サンプル数
組み込み関数でグラフを描く時、default のサンプル点が足りなくて正しく表示されないになる(ガタガタになる)ことがある。そんなときは
set sample 10000
みたいにすれば、10000 点のデータで描いてくれる

!式(関数)の定義
ずっと知らずにいたのだけど、式を定義することができる。(今まで変数定義しか知らなかった。)なので、
> a(x)=sin(x)
> b(x)=cos(x)
> plot a(x)*b(x)
とやれば sin(x)*cos(x) を描いてくれる。今更ではあるが、、、

!標準入力から渡される数値データでグラフを描くには
次のようにすれば、標準入力 '-' から渡されるデータ列からグラフを描くことができる。(仮に hoge.d なるデータファイルがあったとして)
cat hoge.d | gnuplot -persistent -e "plot '-' with l"
-e オプションの後の "" の間に、gnuplot でのコマンドを列挙することができる。(但し " はエスケープして \" とすること)

!animation
上の方で for と sprintf を使い複数のファイルを順次描かせる方法について記述したが、1つのデータファイル内に改行2つで区切られた複数データを記述することでも同様のことができる。つまり、次のようなフォーマットのデータファイルを用意し
0.0 1.0  # index 1 の先頭行
0.1 3.0
0.2 2.0
          # 異なるデータセット間に 2つ改行を入れる

0.0 1.1  # index 2 の先頭行
0.1 3.2
0.2 2.3


0.0 1.0  # index 3 の先頭行
0.1 3.1
0.2 2.4
このようなデータファイル hoge.d を使って、gnuplot 内で次のように
gnuplot> f="hoge.d"
gnuplot> do for [i=0:2] { plot f index i using 1:2; pause 0.5;}

!gif animation の作り方
上の連続プロットを、 set term gif animate して実行することでアニメーションgifを作ることができる。
set term gif animate delay 20 optimize size 800,600
set output "hoge.gif"
do for [i=0:2] { plot "hoge.d" index i using 1:2}
delay 20 は 20x0.001sec 間隔、size 800x600 の optimize されたファイルを hoge.gif に出力する、という意味。

!gif animation のファイルサイズ縮小
上の方法で作られた gif animation はファイルサイズが結構大きい。Imagemagick の convert コマンドによってファイルサイズを小さくすべし。

 {{attach_view('wavepacket.gif')}} オリジナルの gif (978K)
!!(その1)Global color table を使う方法
以下のように +map を付けて変換することで、全コマ共通の Global カラーテーブルにでき、ファイルサイズを減ずることができる。
convert original.gif +map converted.gif
(解説)gif animation のカラーテーブルには、コマ毎に別のカラーテーブルを持つ Local カラーテーブルと、全コマ共通の Global カラーテーブルがあるとのこと。コマ毎にテーブルを持つ Local の方がファイルサイズが大きい。上の gif animation の場合、+map 付きで変換すると 887K になる。

!!(その2)-layer Optimize を使う方法
-layers Optimize というオプションを付けることで、途中のフレームをフレーム間で差異のある部分の差分で表すことができる。
convert original.gif -layers Optimize converted.gif
多くの gif 動画では、変化の部位が限られるはず。ここで挙げたような animation だと変化している部分は波のところだけなので、効果的にファイルサイズを小さくすることができる。下は -layers Optimize したものだが、見るかぎりにおいては original と何ら違いはないにも関わらず、ファイルサイズは 159K に減ずることができている。

 {{attach_view('wavepacket-layersOpt.gif')}} -layers Optimize (159K)

「フレーム間の差で表す」という意味が分からないかもと思うので、この -layers Optimize した gif の 50 フレーム目を抜き出してみると次のようになる。

 {{attach_view('wavepacket-layerOpt50.gif')}} -layers Optimize したgif の 50 フレーム目

分かりにくいかもしれないが、変化のあるところ以外は透明になっている。

!!一般的には
その1とその2の両方合わせて次のようにすると良いハズ。
convert original.gif +map -layers Optimize converted.gif

!!gif animation ファイルの resize (geometry 変換)
-layers Optimize した gif animation を resize する(例えば thumb nail とか作るときの話)ときは注意が必要。各フレームが差分なので、中々変な変換ファイルができあがる。元の gif ファイルを resize した後に -layers Optimize する方がよいみたい。あるいは、次のように最初のフレームのみで resize するのがよいだろう。
convert -resize 180x120 'original.gif[0]' thumbnail.gif

!labelの位置
通常データの x,y 座標を使って指定する
set label 1 "hogehoge" at 10.0, 20.0
x,y座標領域
!labelの位置
xrange やgraph
データの
yrange を変更しても、x,y 座標ではなくグラフの特定位置に label を配置したいことがあるが、この場合には配置したい時は次のように graph を指定すれば良い。グラフの左下を 0,0 右上を 1,1 とする graph を使えば良いとして指定可能。
set label 2 "ahoaho" at graph 0.2, 0.9

!title
マウスでぐりぐり動かす splot などの場合、label ではなく、title を使って図の説明(タイトル)を入れるのが吉
set title "hogehoge \n ahoaho"
\n を入れれば改行できる

!fit
最小二乗法による数値データのフィッティング機能 fit について。
たとえばコーシー分布にフィットするには次のようにパラメータ a,b,c を使って関数を定義し定義した上で fit を実行すれば良い(書くまでもないと思うが data.d は fit したいデータファイル)
f(x)=a/((x-b)**2 + c**2)
fit [0.1:0.5] f(x) "data.d" u 1:3 via a,b,c
なお [0.1:0.5] は 0.1 から 0.5 の範囲でフィットせよという意味。なお
なお default で a=b=c=1 という初期条件で探すので、もし収束が悪い場合は予め初期値を設定して fit すればよい。

fit を実行すると、最小二乗法により parameter を探していく。その結果は gnuplot console に表示しつつ、fit.log ファイルに追記されていく。なお、fit 実行時の画面表示は標準出力ではなく標準エラー出力なので、shell script でゴニョゴニョするときは標準エラー出力を利用すること。

fitting parameter を表示するには、gnuplot コンソール上であれば
print a
とすればよいし、label としてグラフの中に埋め込むのであれば sprintf 関数を利用して
set label 1 sprintf("a=%f b=%f", a, b) at graph 0.1,0.9
のようにすればよい。