「gnuplot」カテゴリーアーカイブ

アニメーションに便利な関数

アニメーションに便利な関数、手法です。

点の表示


plot sprintf("< echo ''%f %f''", x0,y0)

とすると点\((x_0,y_0)\)が描写されます。

窓関数


窓関数です。関数\(W(x)\)は、
\(
\displaystyle W(x)=\frac{r^{2^n}}{(x-x_c)^{2^n}+r^{2^n}}
\)
書かれます。この関数は\(r\)が窓の横幅を示し、\(n\)が窓の端の様子を決めるパラメータです。窓の広がりはおよそ\(2r\)です。

fwi(n,r,i,ic)=(real(r)**(2**n))/((real(i-ic))**(2**n)+real(r)**(2**n))

加速、減速


extanh
\(
\begin{align}
y(x)&=C_0\tanh(a(x-x_c))+C_1 \\
& C_0 = \frac{f_0-f_1}{t_0-t_1} \\
& C_1 = \frac{-t_1f_0+t_0f_1}{t_0-t_1} \\
& t_0 = \tanh(a(x_0-x_c)) \\
& t_1 = \tanh(a(x_1-x_c)) \\
& x_c = \frac{x_0+x_1}{2}
\end{align}
\)
の関数は点\((x_0,y_0)\)から点\((x_1,y_1)\)に\(\tanh(ax)\)で与えられる関数で書きます。
関数の中心は\((x_c,y_c)=((x_0+x_1)/2,(y_0+y_1)/2)\)になります。
画像の2つの赤い点は\((x_0,y_0)\)と\((x_1,y_1)\)を表しています。
\(a\)は変化の度合いを調節するパラメータです。

この関数は非常に使えます。ラミエルを作っている最中にこの関数を考えましたが、想像以上に役立ちます。

fth(a,x,x0,f0,x1,f1)=(f0-f1)*tanh(a*(real(x)-(x0+x1)*0.5e0))/(tanh(a*(real(x0)-(x0+x1)*0.5e0))-tanh(a*(real(x1)-(x0+x1)*0.5e0)))+(-f0*tanh(a*(real(x1)-(x0+x1)*0.5e0))+f1*tanh(a*(real(x0)-(x0+x1)*0.5e0)))/(tanh(a*(real(x0)-(x0+x1)*0.5e0))-tanh(a*(real(x1)-(x0+x1)*0.5e0)))
 # x0,f0 --> x1,f1

この関数を用いた応用です。
extime_tanh

これはある時間内で高さを反転させるものです。コードはこちら。

set xr[-6:6]
set yr[0.8:2.2]
set size ratio 0.5 1
   
a=1e0
at=0.4e0
x0=-5e0
f0=1e0
x1=5e0
f1=2e0

#set term gif enhanced animate optimize delay 8 size 800,500
#set output 'extime_tanh.gif'

i0=0
i1=20
do for[i=i0:i1]{
    ft0=fth(at,i,i0,f0,i1,f1)
    ft1=fth(at,i,i0,f1,i1,f0)
    plot fth(a,x,x0,ft0,x1,ft1) w l lt 2 lc 3 lw 5 ti sprintf("a=%3.2f, at=%3.2f, (x_0,f_0)=(%3.2f,%3.2f), (x_1,f_1)=(%3.2f,%3.2f)",a,at,x0,f0,x1,f1), sprintf("< echo ''%f %f''", x0,ft0) pt 7 ps 2 lc 7, sprintf("< echo ''%f %f''", x1,ft1) pt 7 ps 2 lc 7

  }

#set out
#set terminal wxt enhanced

三角波、のこぎり波、矩形波、その他の数式

正弦波ではない周期関数、三角波、矩形波等々の数式による表現です。
if文は使っていません。
床関数\(floor(x)\)を主に用いています。

これらが唯一の作り方ではなく、最善の作り方でもありません。

非連続になる関数の場合の特定な関数の場合、中間の値を取るようにしています(フーリエ級数の収束より)。


階段関数

——-
f1
z_f1_x_c
——-
f2
z_f2_x_c
——-
fl
z_fl_x_c


のこぎり波

s1
z_s1_x_c
s2
z_s2_x_c
saw
z_saw_x_c


矩形波

k1,k2,k,ka,kb,kk
z_k1_abx_c

z_k2_abx_c

z_k_abx_c

z_ka_abx_c

z_kb_abx_c

z_kk_abx_c


その他

sl,s,spk
tr,se,de,mo
well1,well2

sl
z_sl_abx_c

s
z_s_ax_c
三角波は、\({\rm acos}(\cos(x))\)とも書けます。

spk
z_spk_abx_c

tr
z_tr_abx_c

se
z_se_abx_c

de
z_de_abx_c

mo
z_mo_abx_c

well1
zwell1_abx_c

well2
z_well2_abx_c

well

追記
\(\displaystyle
f(a,b,x) = sgn(abs(2*(x-b)/a)-1e0)
\)
でokです。aは井戸の幅、bは井戸の中心を示します。


まとめ
periodic_functions_c

全てをまとめたgnuplotのコードは以下のものです。

set size ratio -1
set yr[-2:2]
set xr[-5:5]
set samples 101
set grid
set xtics 1
set ytics 1
set mxtics 2
set mytics 2

f1(x)=floor(x)
f2(x)=-floor(-x)-1e0
fl(x)=0.5e0*(floor(x)-floor(-x)-1e0)

s1(x)=x-floor(x)
s2(x)=x+floor(-x)+1e0
saw(x)=x-0.5e0*(floor(x)-floor(-x)-1e0)

k1(a,b,x)=f1((x+a)/(a+b))-f1(x/(a+b))
k2(a,b,x)=f2((x+a)/(a+b))-f2(x/(a+b))
k(a,b,x)=fl((x+a)/(a+b))-fl(x/(a+b))
kk(a,b,x)=2e0*(k(a,b,x)-0.5e0)

ka(a,b,x)=0.5e0*(sgn(k(a,b,x)-0.25e0))+0.5e0
kb(a,b,x)=0.5e0*(sgn(k(a,b,x)-0.75e0))+0.5e0

sl(a,b,x)=kk(a+b,a+b,x+0.5e0*b+a)*k(a,b,x)

s(a,x)=2e0*abs(s2(x/(a*2))-0.5e0)*kk(a*2e0,a*2e0,x+a)
tr(a,b,x)=k(a,b,x)*s(0.5e0*(a+b),x-0.5e0*b)*(1e0+b/a)+sl(b,a,x-b)

spk(a,b,x)=-abs(kk(a,b,x))+1e0

se(a,b,x)=(x-b-(a+b)*fl(x/(a+b)))/a*k(a,b,x)+0.5e0*(k(a,b,x)*(1e0-b/a)+1e0)*spk(a+b,a+b,x)

de(a,b,x)=-se(a,b,x)*2e0*(k2(a+b,a+b,x-0.5e0*b)-0.5e0)
mo(a,b,x)=de(a*0.5e0,b+a*0.5e0,x+a*0.5e0)+de(a*0.5e0,b+a*0.5e0,-(x+a*0.5e0))

well1(a,b,x)=0.5e0*(sgn((abs(2e0*(x-b)/a)-1e0)+ka(1e0,1e0,abs(2e0*(x-b)/a))-0.5e0))+0.5e0
well2(a,b,x)=0.5e0*(sgn((abs(2e0*(x-b)/a)-1e0)+kb(1e0,1e0,abs(2e0*(x-b)/a))-0.5e0))+0.5e0

gnuplotで配列を使う

gnuplotで配列はver5.0の時点では実装されていません。
文字を利用することで疑似的な配列が使えます。

まとめ


配列の名前を ” a ” として考えます。

a = ''
do for [i = 1:5] {
    a = a . sprintf('%f ', 0.2*i)
}

plot for [i=1:5] word(a,i)*x

とスクリプトを書き、プロットすると
arraygnuplot2
という画像が得られます。

配列の利用


gnuplotでは配列が実装されていません。
doループがver4.6から実装されたことから、これから実装されるかもしれません。

今、
\(
y=0.2x,\;\;0.4x,\;\;0.6x,\;\;0.8x,\;\;x
\)
の合計5つの関数をプロットしたいとします。
もしも素直に考えるならば、スクリプトは

plot for [i=1:5] i*0.2*x

です。これくらいは簡単ですが、複雑になった場合はどうでしょう。そのために疑似配列の使い方を知っておきましょう。

gnuplotで配列は実装されていないので、配列に似たもの(疑似配列と呼ぶことにします)を作ります。
普通のプログラミングでの”配列”のイメージは、番号付けした変数をデータの数だけ用意し、そこに代入していくイメージです。すなわち、
\(a(1)=0.2,\;\; a(2)=0.4,\;\; a(3)=0.6,\;\; a(4)=0.8,\;\; a(5)=1\)
という具合にです。

が、gnuplotでの疑似配列は、空白によって値と値が分けられた1つの文字型変数を用いて作ります。すなわち、
\(a= ” 0.2\;\; 0.4\;\; 0.6\;\; 0.8\;\; 1″ \)
を用意し、呼び出し時に
word(配列名、番号)
というgnuplotに用意されている関数を用いてそれぞれの要素にアクセスします。

この疑似配列aの作り方はこうです。

a = ''
do for [i = 1:5] {
    a = a . sprintf('%f ', 0.2*i)
}

1行目は配列”a”の初期化です。
2~4行目は配列”a”に実際に値を入れていきます。
この形を覚えておけば配列を作ることができます。

配列の呼び出しは、word(,)を用います。1つ目の引数に対象の疑似配列、2つ目の引数に何番目の要素を呼び出すかを指定します。以下のように、

a = ''
do for [i = 1:5] {
    a = a . sprintf('%f ', 0.2*i)
}
plot for [i=1:5] word(a,i)*x

とすればグラフとして書き出されます。

[adsense1]

疑似配列の四則演算


疑似配列の要素に数字を加えたいとします。
その場合は

b = ''
do for [i=1:5] {
   b = b . sprintf('%f ',word(a,i)+1)
}

とすれば疑似配列bに疑似配列aのそれぞれの要素に1加えた値が格納されます。
※同じ配列aにその結果を格納したい場合は最後にa=bを付け加えてください。

疑似配列同士の和を取りたければ、

c = ''
do for [i=1:5] {
   c = c . sprintf('%f ',word(a,i)+word(b,i))
}

とすれば疑似配列\(c(i)\)に(疑似配列\(a(i)\))+(疑似配列\(b(i)\))の値が格納されます。
差ならば-, 積ならば*, 商ならば/に変えてください。

実際に、以下のスクリプトを動かしてみます。

a = ''
do for [i = 1:5] {
    a = a . sprintf('%f ', 0.2*i)
}
print a

b = ''
do for [i=1:5] {
   b = b . sprintf('%f ',word(a,i)+1)
}
print b

c = ''
do for [i=1:5] {
   c = c . sprintf('%f ',word(a,i)*word(b,i))
}
print c

とすると実行結果

gnuplot> load "array.plt"
0.200000 0.400000 0.600000 0.800000 1.000000
1.200000 1.400000 1.600000 1.800000 2.000000
0.240000 0.560000 0.960000 1.440000 2.000000
gnuplot>

を得ます。

応用例


半径の違う複数の球
A = ''
do for [i = 1:5] {
    A = A . sprintf('%f ', 1e0/i)
}

set parametric
set ur[0:pi]
set vr[0:2*pi]
set key below
set ticslevel 0

set view equal xyz

splot for [i=5:1:-1] word(A,i)*sin(u)*cos(v),word(A,i)*sin(u)*sin(v),word(A,i)*cos(u)

というスクリプトを用いますと、半径の違う球が掛けます。
sp_argnuplot_c

アニメーション
num=5
A = ''
do for [i = 1:num] {
    A = A . sprintf('%f ', 1e0/i)
}

do for [j=1:119] {
   t=0.05*j
   set view 68,j*1.5,1,1
   A=''
   do for [i = 1:num] {
       A = A . sprintf('%f ', 1e0/sqrt(1+10*sin(t+i*(2e0*pi)/num)**2))
       }
   splot for [i= num:1:-1 ] word(A,i)*sin(u)*cos(v),word(A,i)*sin(u)*sin(v),word(A,i)*cos(u)
}

を表示に関する設定をして実行すると下のアニメーションが得られます。
sphere3

参考文献


Operate on 1D arrays in gnuplot

[adsense2][adsense3]

角度に依存して色を付ける(gnuplot)

gnuplotです。
gnuplotで、関数、もしくはデータでsplotすると3列目のデータに依存してカラーリングがされます。新たに4列目にデータを加え、splotをする時に

splot "test.d" u 1:2:3:4 w pm3d

とすると、4列目に従ったカラーリングがされます。

データの場合


例えば、以下のデータ(球面調和関数\(l=1,m=0\))を持っていたとします。
(ここにテキストデータ”y10.d”(500kB)を置きました。)
1列目:\(\sin{\theta}\cos{\phi}\cdot Y_{l,m}\), 2列目:\(\sin{\theta}\sin{\phi}\cdot Y_{l,m}\), 3列目:\(\cos{\theta}\cdot Y_{l,m}\), 4列目:\(\theta\), 5列目:\(\phi\)
そのまま出力する場合、以下のようなスクリプトで、以下の画像が取得できるはずです。

set pm3d
set pm3d depthorder
unset sur
set view equal xyz
set ticslevel 0
splot "y10.d" u 1:2:3

Ylm_eq_Y10_c

これを角度\(\theta\)に依存させて、形は変えずに色を付けましょう。
splotするときに、カラーを4列目に沿って付けるとすれば、

splot "y10.d" u 1:2:3:4 w pm3d

であり、もしも角度\(\phi\)に依存させて描くのであれば

splot "y10.d" u 1:2:3:5 w pm3d

でokです。実際に書いて、出力するとそれぞれ以下のような画像が出力されます。
y10_normaly10_thetay10_phi
※左から3列目(\(Y_{l,m}\)の値)に従って付けたカラー、4列目\(\theta\)に従って付けたカラー、5列目\(\phi\)に従って付けたカラー
となります。

※球面調和関数の出力に関して
球面調和関数は球面座標で\(\theta,\phi\)の関数\(Y_{l,m}(\theta,\phi)\)です。
ただし、今出力したい座標はデカルト座標(\(x,y,z\))です。デカルト座標で球面座標で記述される画像を得たい場合は単位ベクトル\(\; \vec{r}/|\vec{r}|\;\)に球面座標の関数を掛ければよいのです。
よって
\(
\displaystyle Y_{l,m}(\theta,\phi)\cdot \frac{\vec{r}}{|\vec{r}|}
\)
を表示すればよい、すなわちgnuplot上では(\(r=1\)の場合)、
1列目に \(x\;\;\to \;\; \sin{\theta}\cos{\phi}\cdot Y_{l,m}(\theta,\phi)\)
2列目に \(y\;\;\to \;\; \sin{\theta}\sin{\phi}\cdot Y_{l,m}(\theta,\phi)\)
3列目に \(z\;\;\to \;\; \cos{\theta}\cdot Y_{l,m}(\theta,\phi)\)
を表示させればokです。

多価関数の場合


続いて、多価関数として有名なリーマン面を出力します。
通常のリーマン面(3列目の高さがカラーの基準)を表示させるには

set pm3d depthorder
set parametric
set ur[0.01:5]
set vr[0:4*pi]
i={0,1}
splot u*cos(v),u*sin(v),real(sqrt(u)*exp(i*0.5*v))

とすれば下にある、左側の画像が得られます。角度に依存したカラーリングをしたい場合、以下のスクリプトでokです。

set isosamples 150
set pm3d depthorder

set table "param1.d"
set parametric
set ur[0.01:5]
set vr[0:4*pi]
i={0,1}
splot u,v,real(sqrt(u)*exp(i*0.5*v))
unset table

set table "param2.d"
plot "param1.d" u ($1*cos($2)):($1*sin($2)):3:($2) w vector
unset table

splot "param2.d" u 1:2:3:4 w pm3d

データでは無く、解析的な関数を直接、別の列を基準にして色付け、出力させることはできないようです。なので、関数を数値的なファイルに出力させるコマンド

set table "data.d"
    ...(ここに数値的に出力させたいグラフをプロット)
unset table

を書いて出力を行わせています。

また、角度を出力させるので周期的なカラーリングが良いと思います。色相環を元に下のカラーマップを使うといいでしょう。

set palette defined(0"#ff0000",1"#ff8000",2"#ffff00",3"#80ff00",4"#00ff00",5"#00ff80",6"#00ffff",7"#0080ff",8"#0000ff",9"#8000ff",10"#ff00ff",11"#ff0080",12"#ff0000")

上のスクリプトを実行すると右図のように、角度に依存したカラーリングがされます。
RiemannRiemann_angle
Riemann_compare2_c

※Riemann面について
Riemann面は
\(
f(z)=Re(\sqrt{z})
\)
で表される多価関数です。
gnuplotで単純に考えて上のグラフをプロットしようとすると、

i={0,1}
splot real(sqrt(x+i*y))

で良いはずですが、これを実際にプロットするとこうなります。
riemann_miss_c

本来は多価関数なのですが、それゆえに上記方法ではgnuplotでは記述されません。
極座標を用いて以下のように考えます。
\(
\begin{align}
f(z)&=\sqrt{z} \\
&=\sqrt{r}e^{i\frac{1}{2}\theta} (0\le \theta\lt 4\pi)\\
\end{align}
\)
であるため、gnuplotでは媒介変数表示u,vを用いて
\((x,y,z)=(u\cos{v},u\sin{v},\sqrt{u}e^{i\frac{1}{2}v})\)
\((u:0\sim \infty, v:0\sim 4\pi)\)
とすればいいのです。

参考文献

gnuplot:値に応じて線に色付け -TN’s blog
gnuplotで数値をファイルに書き出す(table)
How to output smooth cspline curve as a data file -Stack Overflow

gnuplotで極座標のグラフを書く

gnuplotで極座標形式\((r,\theta)\)で、こんな感じの2次元のグラフ
GPB-Concept-Dgrm-lg
Spacetime is warped and twisted by the
mass and spin of the earth. -GRAVITY PROBE B Testing Einstein’s Universeより

の、緑色のようなグラフを書きたいと思ったのが始まりです。
グラフの式を以下のように適当に書きます。
\(
\displaystyle \displaystyle f(r)=-\frac{1}{r^2+1}
\)

とモデル化しましょう。これを2つの方法でプロットします。

[adsense1]

gnuplot上で

    splot -1/(x*x+y*y+1)

とすると、
lorentz_c
というように出力されます。

上の場合、これはグリッドがx,y方向に切られています。動径方向と角度方向に切りたい場合はどうすればいいでしょうか。

gnuplotでこれを実現する方法は少なくとも2つあります。

  1. データとしてファイルを作った後、splot
  2. 媒介変数表示を使う

です。今回は2番目の媒介変数表示を使って表示させます。

とりあえず、これで目的のグラフを得ることができます。

set parametric
set ur[0:5]
set vr[0:2*pi]
splot u*sin(v),u*cos(v),-1/(u**2+1)

でこのようになります。
lorentz_sph_c

仕組みは極座標とは
\(
\begin{align}
x&=r\cos\theta \\
y&=r\sin\theta
\end{align}
\)
なので、媒介変数urに、vθをとみなせば書くことができます。

[adsense2]

3dプロットでの破綻


表面をカラー表示にしたいと思った時に、カラーに破綻が起こりました。

    set parametric
    splot u*sin(v),u*cos(v),-1/(u**2+1)
    set ur[0:5]
    set vr[0:2*pi]
    set pm3d at s
    unset sur
    rep

とするとこうなりました。
break_c

これを解決するには

set pm3d depthorder

を追加してreplotすれば破綻しなくなります。set hidden3d のカラー版ですね。
depthorder_c

参考
gnuplot demo script: surface2.dem

gnuplotとアニメーション

gnuplot上の様々なアニメーションを作ります。
dofor構文を使うのでgnuplot ver4.6以降じゃないとこの方法は出来ません。

  1. 解析解の表示
    1. 1次元のアニメーション
    2. 2次元のアニメーション
    3. 点をグラフ上に沿って動かす
    4. グラフをだんだんと書く
  2. データの表示
    1. 複数のデータを次々とプロット
    2. 複数のデータの同時プロット
    3. グラフをだんだんと書く
  3. 応用
    1. グラフを回転させる
    2. 大きさの違う球体
    3. PSO2の転送装置
    4. 「見せてあげよう!ラピュタの雷を!!」
    5. 魔女の宅急便
    6. 第5使徒ラミエル1
    7. 第5使徒ラミエル2
    8. 魔貫光殺砲
    9. マリオ
    10. SCP-1968 「世界を包む逆因果の円環」っぽい数式
    11. FGO召喚
    12. パンジャンドラム
  4. 動画の作成について
    1. gifアニメの作成方法
    2. ffmpegを用いてavi動画を作る

[adsense1]

1次元の場合の具体例


試しに量子力学で現れる、ガウシアン波束の時間発展を考えましょう。
こんな形の方程式を考えます。
\(
\displaystyle y(x,t)=\left(\frac{1}{1+t^2}\right)^{1/2}\exp\left[-\frac{(x-t)^2}{1+t^2}\right]
\)

これをgnuplot上で時間発展させるスクリプトはこちら。

do for [i = 0:400 ] {
   t=i*0.02
   plot sqrt(1/(1+t*t))*exp(-(x-t)**2/(1+t*t))
   }

適宜xrangeとかyrangeとか変更してください。実行するとこんな感じ。
gauss_low

上のgifアニメを得るには、

set term gif animate optimize delay 2 size 480,360
set output 'movie.gif'

do for [i = 0:400 ] {
   t=i*0.02
   plot sqrt(1/(1+t*t))*exp(-(x-t)**2/(1+t*t)) lw 2
   }

set out
set terminal wxt enhanced

というスクリプトを使ってください。
同ディレクトリにmovie.gifが作成されます。
ターミナルとかは各々の環境に合わせてください。

2次元の場合の具体例


2次元だろうとこのように簡単にできます。
gauss2d_analytic
上の動画のスクリプトはこれです。gifアニメが欲しい場合はコメントアウトを外してください。

#set term gif animate optimize delay 10 size 480,480
#set output 'movie.gif'

set pm3d at b
set xr[-5:10]
set yr[-5:10]
set zr[0:1]
set cbr[0:1]
set isosamples 50

do for [i = 0:50 ] {
   t=i*0.05
   splot sqrt(1/(1+t*t))*exp(-(x-t)**2/(1+t*t))*sqrt(1/(1+t*t))*exp(-(y-2*t)**2/(1+t*t))
   }

#set out
#set terminal wxt enhanced

点をグラフ上に沿って動かす


parameter
のような動画を作りたいとします。この時は、媒介変数を用いて以下のスクリプトで再現されます。

#set term gif animate optimize delay 5 size 960,720
#set output 'movie.gif'

set param
set size ratio -1
set samples 10000

e = 1
omega=0.1

set tr[1:600]
do for [i = 1:200 ] {  
   plot e*cos(omega*t)/sqrt(t), sin(omega*t)/sqrt(t)
   set label 1 point pt 7 ps 3  at e*cos(omega*i*3)/sqrt(i*3),sin(omega*i*3)/sqrt(i*3)
   }

#set out
#set terminal wxt enhanced

点の表示は、

set label 1 point pt 7 ps 3  at e*cos(omega*i*3)/sqrt(i*3),sin(omega*i*3)/sqrt(i*3)

の文である1点だけを表示することができます。

グラフをだんだんと書いていく


グラフをちょっとずつ書いていきます。
解析的な解の場合
orbit

set param
set samples 10000
set tr[0.01:1]
imax=100
tmax=20e0*pi
ht=tmax/real(imax)

#set term gif animate optimize delay 6 size 600,600
#set output 'orbit.gif'

do for [i=1:imax] {
   th(t,i)=t*real(i)*ht
   plot 10e0*sin(th(t,i))/th(t,i),10e0*cos(th(t,i))/th(t,i) , \
   10e0*sin(th(t,i)-pi)/th(t,i),10e0*cos(th(t,i)-pi)/th(t,i) lt 1 lc 2
}

#set out
#set terminal wxt enhanced

データの場合(200行のデータ”outgraph.d”を一行目から順番に出力したい場合)

do for [i=1:200]{
   plot "outgraph.d" every ::0:0:i:0 using 1:2 w l
}

グラフを回転させる


ある3Dプロットがあり、それを回転させてみるような動画がほしいとします。例えばこんな感じのアニメーションが作りたいとします。
Riemann
これはリーマン面と呼ばれる関数です。(カラーバーの消去は ‘unset colorbox’ とすれば消せます。)
詳しい記述は角度に依存して色を付ける(gnuplot)に書いてあるので気になる人は参照してください。

set pm3d depthorder
set parametric
set ur[0.01:5]
set vr[0:4*pi]
i={0,1}
splot u*cos(v),u*sin(v),real(sqrt(u)*exp(i*0.5*v))

#set term gif animate optimize size 480,360
#set output 'movie.gif'

do for [j = 0:90 ] {
   set view 60,4*j,1,1
   replot
}

#set out
#set terminal wxt enhanced

参考先はamesyabodyの記述したモンテカルロ法のページからです。

複数のデータを次々とプロット


複数のデータを時間経過を表示させる場合はデータfort.100, fort.101, fort.102,…を用意し、dofor構文の中を変えて、

#set term gif animate optimize size 480,360
#set output 'movie.gif'
do for [j = 100:200 ] {
   splot sprintf("./fort.%d", j) u 1:2:3 w l t sprintf("./fort.%d", j)
}

#set out
#set terminal wxt enhanced

してloadすればいいです。

複数グラフの同時プロット


gnulotofdata_c
data1.d, data2.d, data3.d,data4.d,data5.d
を同時に出力したい時は、

plot for [i=1:5] sprintf("data%d.d",i) w l ti sprintf("data%d.d",i)

とすればいいです。

大きさの違う球体


sphere3

PSO2の転送装置


PSO2の転送装置gnuplot

「見せてあげよう!ラピュタの雷を!!」


bulse2

魔女の宅急便


魔女の数式はこちらです。
witch like curve -wolfram alpha

kiki

第5使徒ラミエル1


ramiel

第5使徒ラミエル2


ramiel_trans

魔貫光殺砲


mk

マリオ


マリオのグラフは↓から。
Mario like curve -wolfram alpha

mario

[adsense2]

SCP-1968っぽい数式


SCP-1968 世界を包む逆因果の円環
に現れている数式です。
数式はTorus helix radius change equationより。

FGO召喚


特定の面と3D視点で見た場合

このリンク先(https://slpr.sakura.ne.jp/qp/supplement_data/FGO_gnuplot.zip)のデータも必要です。
(なんか良く分かりませんがメジェド様がバグるんですよね…)
▼ここクリックでこの場に展開

パンジャンドラム


gifアニメについて


gifアニメの描画時間を早くしたり遅くしたりするには、

set term gif animate delay 10 optimize size 480,360

などと「delay 10」という文を付け加えましょう。delayは遅延、後ろの数字は遅延時間で、単位は0.01sになっています。
例として、
delay 5の場合は1秒間に20枚、
delay 10の場合は1秒間に10枚、
delay 50の場合は1秒間に2枚
表示させるスピードだということです。
delayはどんなに早くしたくても4程度までがいいです。delayを1とかにするとそんなに早いgifアニメの描写が出来ず、ブラウザ上でうまく表示できず、結果として遅く表示されます。

Gif -gnuplot 4.2

ffmpegを用いてavi動画を作る


ffmpegのインストール方法はCompile FFmpeg on Ubuntu, Debian, or Mintを参考にしてください。
このページにもインストール方法を書きましたが、更新が早いので公式のページを見るほうが確実です。
ここではgnuplotの視点を変更した画像をたくさん用意して動画を作成する、という方法をとります。
ディレクトリ”dat/”と視点変更と連続した画像を出力するスクリプトは”image.plt”というファイルを用意して

do for [j = 0:180 ] {
   set view 60,2*j,0.5,3
   replot
   
   call "out.plt" "temp"
   
   if(0<=j && j<10){
      cv=sprintf("mv temp.jpg ./dat/image0000%d.jpg",j)
      }
   if(10<=j && j<100){
      cv=sprintf("mv temp.jpg ./dat/image000%d.jpg",j)
      }
   if(100<=j && j<1000){
      cv=sprintf("mv temp.jpg ./dat/image00%d.jpg",j)
      }
   if(1000<=j && j<10000){
      cv=sprintf("mv temp.jpg ./dat/image0%d.jpg",j)
      }
   if(10000<=j && j<100000){
      cv=sprintf("mv temp.jpg ./dat/image%d.jpg",j)
      }
   system cv   
}

#Using Imagemagick, convert
#cv=sprintf("convert -delay 20 -resize 100% -loop 0 ./dat/image*.jpg ./anime.gif")

#Using ffmpeg
cv=sprintf("ffmpeg -r 12 -i './dat/image%05d.jpg' -vcodec mjpeg -qscale 0 -s 1300x888 movieout.avi")
system cv

とすればディレクトリ./dat/の中に180枚の.jpg画像が作られ、その場所にファイル名”movieout.avi”という動画が作られます。

gnuplotのカラーマップ

配色(pm3dの色)について
gnuplot ver4.6で確かめています。

一番良いと思ったカラーマップは、matlabで使われている”jet”だと感じました。

set palette defined ( 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#90ff70',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

colorjet
参考:Matlab colorbar with Gnuplot

※一番下に黒または白を追加した以下の物も良いと思います。

set palette defined ( -1 '#000030', 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#90ff70',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

set palette defined ( -1 '#ffffff', 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#90ff70',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

※正負をはっきりと見せたい時。

set palette defined ( 0 '#0fffee',1 '#0090ff', 2 '#000fff',3 '#000090',4 '#ffffff',5 '#7f0000', 6 '#ee0000', 7 '#ff7000', 8 '#ffee00')

set palette defined ( 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#ffffff',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

追記)2023/01/13
matlabでは、最近parulaというカラーマップが採用されているようです。

set palette defined ( 0 '#352a87',1 '#2053d4',2 '#0d75dc',3 '#0c93d2',4 '#07a9c2',5 '#38b99e',6 '#7cbf7b',7 '#b7bd64',8 '#f1b94a',9 '#fad32a',10 '#f9fb0e')

グレースケールにした時にも画像を変更する必要もなく、このままで綺麗に出るようです。
また、\(f(x,y)=\sin(xy)\)をjetと比較してみましょう。

グレースケールとした場合は、以下のようになります。

確かにparulaの方が高い低いがはっきりと分かります。

カラーの場合は偏りが生じないjetの方が綺麗ですかね?
しかし、parulaの方が柔らかな印象です。
グレースケールで印刷されることが予想されるならば、parulaの方がいいですね。
印象が大きく変わるかと思います。好きな方をご使用ください。


配色について。
gnuplotでは色の指定方法として3種類あるそうです((2),(3),(4))。

お勧めのカラーの指定順に,
(1)外部サイトgnuplottingにあるカラーマップを利用する
(2)cubehelixで指定する
(3)definedで指定する
(4)rgbformulaeで指定する

方法を紹介します。

(1)gnuplottingにあるカラーマップの利用


一番早く、綺麗なカラーマップを得るためには”gnuplotting(http://www.gnuplotting.org/)”という外部サイトに紹介されているgnuplotのカラーマップを使うことです。
ここに紹介されているカラーマップは、https://github.com/Gnuplotting/gnuplot-palettesより画像を引用して、
overview((c)gnuplotting)です。

使い方
  1. Gnuplotting/gnuplot-palettes -githubに飛びます。
  2. 右上にある “Clone or download” をクリックしてすべてのファイルをダウンロード
  3. カラーマップを見て使いたい名前の “***.pal” ファイルをgnuplot上でload
    で使えます。線の色なども上書きされるので、もしも線の色だけを変えたければ、linestyleなどで変更する必要があります。

(2)cubehelixで指定する


gnuplot version4.6以上

set palette cubehelix start 0.5 cycles -1.5 saturation 1

この色の指定方法はD.A.Greenによって発表された、宇宙の、強度イメージを色付けするために作られた色の指定方法です[1]。

それぞれのパラメータが何を表すかは折りたたんでおきますので、気になる方は下のリンクを開いてください。

[adsense1]

cubehelixでの具体例

対象とするデータは、水素原子の(n,l,m)=(4,2,0)の解析解です。
※このデータが欲しい方はこちらHydrogen_xz_nlm420.txt(1.5MB)に置きましたので、コピペしてください。
Ctrl+aで全選択できます。

3Dの表示ではこういうグラフです。
hydrogennlm420

特に記述が無いものはgammaの値はデフォルトの1.5です。

1.hydro420_s0.5c-1.5s1g1.5_c

set palette cubehelix start 0.5 cycles -1.5 saturation 1

きちんとした裏付けの下カラーリングされているので、論文等々にお勧めです。


2.hydro420_s0.5c-1s3g1.5_c

set palette cubehelix start 0.5 cycles -1 saturation 3

もしくは

 set palette defined(0"#000000",1"#5b13b8",2"#1c60ff",3"#00b7d8",4"#01eb75",5"#55f02e",6"#ccd73b",7"#ffc68c",8"#ffd5e2",9"#ffffff")

3.hydro420_s0.5c-1s3g3_c

set palette cubehelix start 0.5 cycles -1 saturation 3
set palette gamma 3

もしくは↑に近い色で

set palette defined(0"#000000",0.1"#8e007a",2.1"#579dff",3.1"#2de4ff",4.1"#4bffab",5.1"#98fe7d",6.1"#e4eb8c",7.1"#ffe1c0",8.1"#ffe9f0",9.1"#ffffff")

4.hydro420_s1c0s2g1.5_c

set palette cubehelix start 1 cycles 0 saturation 2

5.hydro420_s2c0s3g1.5_c

set palette cubehelix start 2 cycles 0 saturation 3

6.hydro420_s2c1s2g1.5_c

set palette cubehelix start 2 cycles 1 saturation 2

7.hydro420_s3c0.5s3g1.5_c

set palette cubehelix start 3 cycles 0.5 saturation 3

8.hydro420_s1c5s3g1.5_c

set palette cubehelix start 1 cycles 5 saturation 3

9.hydro420_s1c0s2g1.5neg_c

set palette cubehelix start 1 cycles 0 saturation 2 negative

10.hydro420_s1c-1s2g1.5neg_c

set palette cubehelix start 1 cycles -1 saturation 2 negative

11.hydro420_s3c0.5s1g1.5neg_c

set palette cubehelix start 3 cycles 0.5 saturation 1 negative

12.hydro420_s3c-2s2g1.5neg_c

set palette cubehelix start 3 cycles -2 saturation 2 negative

13.hydro420_s1c5s3g1.5neg_c

set palette cubehelix start 1 cycles 5 saturation 3 negative

82.54.4 Cubehelix

(3)definedで指定する

set palette defined(-3"blue",0"white",5"red",10"yellow")

z軸が-3になったとき青色(blue)、0になったとき白(white),5になったとき赤(red)、10になったとき黄色 (yellow・になるような配色です。
zの範囲が-50 < z < 100だった場合は-3,0,5,10の比で表されます。
すなわち、z=-50で青、z=-16付近で白、z=42付近で赤、z=100で黄色となるように自動的に調整されます。
色は有名な色は上の例のように言葉で記述できますが、16進数のカラーコードによる表示もできます。

カラーマップ例

カラーマップ例を載せます。


set palette defined ( 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#90ff70',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

matlabで使われている”jet”のカラーマップです。
colorjet
参考:Matlab colorbar with Gnuplot

set palette defined(0"#ff0000",1"#ff8000",2"#ffff00",3"#80ff00",4"#00ff00",5"#00ff80",6"#00ffff",7"#0080ff",8"#0000ff",9"#8000ff",10"#ff00ff",11"#ff0080",12"#ff0000")

cyclic_c
色は色相環を元に作っています。
周期的な関数を出力するときに役に立ちます。例えば、リーマン面を角度に依存させて表示する際などに利用すると良いです。こんなように。
Riemann_angle


set palette defined(1"#0000ff",2"#0080ff",3"#00ffff",4"#00ff80",5"#00ff00",6"#80ff00",7"#ffff00",8"#ff8000",9"#ff0000")

cl2_c
色相環を元に作成したものです。


set palette defined (-9 "purple",-6 "blue",-3 "turquoise", 0 "#f5f5f5", 3 "gold", 6 "orange", 9 "red")

cwhite
※匿名希望さん提供


set palette defined(0"#ffffff",0.8"#00008b",1.8"#2ca9e1",3"#008000",4.2"#ffff00",5"#eb6101",5.5"#8b0000")

カラフルtr_c
白⇒青⇒水色⇒黄色⇒オレンジ⇒赤
細かい変化を見たい時にいい感じになります。


set palette defined(0"#000000",1"#0000ff",2"#1e90ff",3"#00ffff")

黒から青tr_c
黒⇒青⇒明るい青
不連続な関数を表示させる時にこのマップを使うといい感じになります。


set palette defined(0"#ffffff",1"#0000ff",2"#ff0000",3"#ffff00")

白青黄tr_c
白⇒青⇒赤⇒黄
上の2つが気に入らなかったりした時に。


set palette defined(0"#00008b",1"#2ca9e1",2"#38b48b",3.5"#ffff00",5"#eb6101",5.3"#c9171e")

カラフルatr_c
青⇒水色⇒黄色⇒オレンジ⇒赤
一番下が白じゃないほうがいいときに。

(4) rgbformulaeで指定する

set palette rgbformulae 33,13,10

”set palette rgbformulae” のあとの3つの整数で赤(R)/緑(G)/青(B)に対応しています。
整数で赤、緑、青をどのような変化具合をさせるのかということを指定します。
直線的に色を変化させるのか、2次、3次関数的なのかはたまたsin,cos的なのかを。どういった整数を使えばどういう関数に相当するのか?
これを知るには gnuplot上で
”show palette rgbformulae”
と打ってください。gnuplot ver.4.6では、以下の画像のように出力されます。
rgbformulae_c
0~36まで出てきます。指定は-36~36までできます。負の値は反転することを意味しています。

また、いくつかのrgbformulaeを使った例が ”help palette rgbformulae” で見れます。実際に入力するとこんな感じ。
helprgb_c
helpで現れるカラーマップはこんな感じです。
rgbformulae_help_c

また、今使っているカラーマップをrgbformulaeで記述をしたい場合、

show palette fit2rgbformulae

とやれば、今使っているカラーマップをrgbformulaeで表示する場合の3つの数字を出してくれます。
あくまで似た図です。

デフォルトのカラーマップを変更する

デフォルトのカラーマップを変更するには、ホームディレクトリにて、
.gnuplot
という名前のファイルを作り、その中に

set palette defined(0"#ffffff",0.8"#00008b",1.8"#2ca9e1",3"#008000",4.2"#ffff00",5"#eb6101",5.5"#8b0000")

と記述します。これでデフォルトのカラーマップが変更されます。

ちなみに、僕が使っている.gnuplotファイルは以下のものです。

set terminal wxt dashed noraise enhanced font 'Times New Roman,20'

#matlab jet
#set palette defined ( 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#90ff70',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

set palette defined ( -1 '#ffffff', 0 '#000090',1 '#000fff',2 '#0090ff',3 '#0fffee',4 '#90ff70',5 '#ffee00',6 '#ff7000',7 '#ee0000',8 '#7f0000')

set linetype  1 lc rgb "black" lw 1
set linetype  2 lc rgb "red" lw 1
set linetype  3 lc rgb "blue" lw 1
set linetype  4 lc rgb "forest-green"
set linetype  5 lc rgb "magenta" lw 1
set linetype  6 lc rgb "#FFD900" lw 1
set linetype  7 lc rgb "cyan" lw 1
set linetype  8 lc rgb "#7F00FF" lw 1
set linetype  9 lc rgb "#FF7F00" lw 1
set linetype  10 lc rgb "#00FF7F" lw 1
set linetype  11 lc rgb "gray" lw 1
set linetype  12 lc rgb "gray40" lw 1

上の設定を適応すると、カラーマップはjetに黒を追加したもの、線は以下のようになります。

配色のあれこれ、gnuplot demoより。
カラフルに塗りたい http://gnuplot.sourceforge.net/demo/pm3dcolors.html
モノクロに塗りたい http://gnuplot.sourceforge.net/demo/pm3dgamma.html
点に色をつけたい http://gnuplot.sourceforge.net/demo/rgb_variable.html
線に色をつけたい http://gnuplot.sourceforge.net/demo/rainbow.html

http://ayapin-film.sakura.ne.jp/Gnuplot/Primer/Misc/colormap.html

[1]D. A. Green(2011), ‘A colour scheme for the display of astronomical intensity images’, Bulletin of the Astronomical Society of India, 39, 289.(2011BASI…39..289G at ADS.)

またDave Green’s `cubehelix’ colour schemeをご覧下さい。

[adsense2]

gnuplotで画像出力

gnuplotで画像を出力したいことがあります。
その方法を書きたいと思います。

想定する環境

  • gnuplot: Version 4.6 patchlevel 4
  • Imagemagick(convertコマンドを使用)

がインストールされている状況を考えます。特に、gnuplotではdofor構文を用いるため少なくともVersion4.6以上出ないと本稿に沿った画像出力はできませんのでご了承ください。

画像出力について

画像出力するための方法として、epsファイルを出力してからjpgやpng形式に変換します(僕がそれしか知らないためです)。

基本的には
ターミナル(x11とかwxtとかaquaとかpostscriptとかgifとか…)の指定→出力ファイル名の指定→グラフをファイルに出力
という流れになります。
手入力で画像出力する場合はgnuplotで

set terminal postscript eps enhanced color
set output "aaa.eps"
replot

とすれば今出力されているグラフの画像が”aaa.eps”というファイル名で得られます。
もしもjpgやpng形式に変換したければImagemagickのconvertコマンドを用いて、

convert -density 300x300 aaa.eps aaa.jpg

とすればjpg形式が得られます。jpgをpngに書き換えればpngが得られます。

しかし、何枚も画像がほしい場合には不向きです。スクリプトを書きましょう。
“out.plt”というファイルを作り、その中にこう書きます。

fname="$0"
set terminal postscript eps solid enhanced color
set output fname.".eps"
replot
set out
set terminal wxt enhanced

# 1. PNG with background
cv=sprintf("convert -density 300x300 %s.eps %s.png",fname,fname)

# 2. PNG with background
#cv=sprintf("convert -density 150x150 %s.eps %s.png",fname,fname)

# 3. PNG with background white
#cv=sprintf("convert -density 150x150 -background white -flatten -alpha off %s.eps %s.png",fname,fname)

system cv

このファイルをgnuplotのcallコマンドを用いて、

call "out.plt" "bbb"

として呼び出します。callは引数を指定できるコマンドです。
すると”bbb.eps”と”bbb.png”ファイルが作成されます。便利だね!

カラーマップの上に線を描く

gnuplotでカラーマップの上に2次元で書かれたグラフを書きたいとします。

この場合は

set pm3d map
splot "fort.11" u 1:2:3 with pm3d, "fort.10" u 1:2:($2-$2) with point

とすればokです。
カラーマップの情報はfort.10, 書きたい線のデータはfort.11に書かれているとします。
考えは、2次元のデータをあたかも3次元のデータとして扱うことで解決します。

coloronplot
上のデータを得るためのfortranコードはこんな感じです。

program main
  implicit none
  double precision::x,y,h
 
  h=5.d-2
  y=-3.d0
  do while(y.le.3.d0)
     x=-3.d0
     do while(x.le.3.d0)
        write(11,*)x,y,x+y
        x=x+h
     enddo
     write(11,*)
     
     write(10,*)y,sin(y)
     y=y+h
  enddo

  return
end program main

818 re(1):pm3dによる等高線図(カラーマップ)に2次元グラフを重ねる方法

裏面の色と隠線処理

gnuplotの通常の表示では隠れて見えない部分も見せようとします。
例えば手前に大きな山があり、後ろは見えないはずですが、格子状にしているとそれが見えてしまいます。表示させないようにするには、

set hidden3d

とすればokです。

set hidden3dをする

hidden3dの効果

また、3D表示において裏面と表面の色を変えたい時は、

set hidden3d back offset 1 trianglepattern 3 undefined 1 altdiagonal bentover

とすればいいです。参考URLの値そのままです。

例えば上の数字のところを変えれば裏面の色を変えることができます。

set hidden3d back offset 2 trianglepattern 3 undefined 1 altdiagonal bentover

とすれば、
hidden3d裏面の色

gnuplot demo script: surface2.demより。