gnuplotでグラデーション

PointやLineなどの色を、例えば赤から徐々に青へと変えていくなどしたい場合、どのようにしたらいいか紹介します。

paletteを使う方法

PointやLineなどの色を系統的に変えていくには、paletteを用いるのが簡単です。

paletteはある実数に対して一つの色を対応させるための関数を指定するものです。あるpaletteを指定すると、withコマンドの中でlinecolor palette frac XとすることでPointやLineなどを実数Xに対応する色にすることができます。

一つ例を示しましょう。

set palette model RGB functions gray,0,0 # gray: 0以上1以下の実数
set key outside 
set rmargin 15
unset colorbox
set xrange [0:8]
plot n=0,   sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n)

上のスクリプトでは、1行目でpaletteを指定しています。オプションmodel RGBはRGB色空間を使用することを指定しています。次のオプションfunctions R(gray),G(gray),B(gray)は、R・G・Bそれぞれの色の強さをどのように変化させるかを指定します。functionsオプションの下ではgrayは0から1まで変化する変数として扱われ、R(gray),G(gray),B(gray)はそれぞれ変数grayに対して0から1までの値を返す関数です。変数grayにはpaletteが呼び出されるときに与えられる実数が直接代入されます。上記の例のpaletteは、例えば0を与えた場合(R,G,B)=(0,0,0)(黒)、1を与えた場合(R,G,B)=(1,0,0)(赤)を返すような関数を指定していることになります。

指定したpaletteを実際にplotの色として使うために、withの中でlc palette frac n/10.0としてpaletteを呼び出しています。fracの後にくる実数(上の例ではn/10.0)に対応する色で関数(or データ)がプロットされます。上の例ではnは0から10までインクリメントされているので、0から0.1、0.2、... 1.0に対応する色が出力されます。

このスクリプトを実行すると、以下のようなグラフが得られます。n=0,1,...,10に対応して黒から徐々に赤に色が変化していることがわかります。実際に使う際はn/10.0の10.0の部分を関数(ファイル)の数や、グラデーションの範囲に応じて適当に変更するといいでしょう。

他の例を示します。

set palette model HSV functions gray,1,1 # HSV color space
set key outside 
set rmargin 15
unset colorbox
set xrange [0:8]
plot n=0,   sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n),\
     n=n+1, sin(x/2+n/10.0) w l lw 4 lc palette frac n/10.0 title sprintf("n=%d", n)

この例ではオプションmodel HSVを用いているので、HSV色空間を使用します。そして、functions gray,1,1なので、H(色相)のみを線形に変化させ、S(彩度)とV(明度)は1に固定する関数を指定していることになります。色相のみを変化させるので、このように虹色のようなグラデーションになります。

別の例を示します。(以下ではset palette ***以外の部分は省略しています。)

set palette model RGB rgbformulae 7,5,15  # traditional pm3d (black-blue-red-yellow)

この例ではfunctionsオプションの代わりにrgbformulaeオプションを使っています。rgbformulaeオプションは予めgnuplotに組み込まれている関数を指定する方法です。どの番号がどのような関数に対応するかを調べるには、コンソールからshow palette rgbformulaeと入力してみてください。例えば、上の例で使っている7,5,15はそれぞれsqrt(x)、x^3、sin(360*x)に対応するようです。すなわち、上の例はset palette model RGB functions sqrt(gray), gray**3、sin(360*gray)set angles radiansされているときはsin(2*pi*gray))としたときと同じ結果になります。

rgbformulaeを使う他の例も示します。

set palette model RGB rgbformulae 35,13,10 #rainbow (blue-green-yellow-red)
set palette model RGB rgbformulae 30,31,32 # color printable on gray (black-blue-violet-yellow-white)

他のrgbformulaeの指定例はgnuplot helpのrgbformulaeの記事をご覧下さい。

自作関数を使う方法

上記のpaletteを使う方法が使えない場合(pm3dとの併用の場合など?)、自作の関数を使ってPointやLineの色を変化させることができます。そのためには、ある整数nを色の名前を表す16進数の文字列"#rrggbb"に変える関数が必要です。

そのような関数の例として、HSV色空間の性質を利用して赤→黄色→緑→青→紫→赤と色を変化させていく関数を紹介します。通常のRGB空間では多数の色の間を滑らかに変化させるのは難しいのですが、HSV空間を使うと、S(彩度)とV(明度)は1に固定しH(色相)を変化させるだけで虹色のようなグラデーションを得ることができます。

## HSV色空間からRGB色空間への変換。Wikipedia参照
#変換の補助関数群
HSV_Hi(h)=sgn(h)*floor(abs(h)/60)%6+(h>=0 ? 0 : 5)
HSV_f(h)=(sgn(h)*(abs(h)-(floor(abs(h))/360)*360.0)/60.0+(h>=0 ? 0 : 6))-HSV_Hi(h)
HSV2R(h,s,v)=( \
     HSV_Hi(h)==0 || HSV_Hi(h)==5 ? v                    : (\
     HSV_Hi(h)==1                 ? v*(1-HSV_f(h)*s)     : (\
     HSV_Hi(h)==4                 ? v*(1-(1-HSV_f(h))*s) : (\
     HSV_Hi(h)==2 || HSV_Hi(h)==3 ? v*(1-s)              : 0.0) )))
HSV2G(h,s,v)=( \
     HSV_Hi(h)==1 || HSV_Hi(h)==2 ? v                    : (\
     HSV_Hi(h)==3                 ? v*(1-HSV_f(h)*s)     : (\
     HSV_Hi(h)==0                 ? v*(1-(1-HSV_f(h))*s) : (\
     HSV_Hi(h)==4 || HSV_Hi(h)==5 ? v*(1-s)              : 0.0) )))
HSV2B(h,s,v)=( \
     HSV_Hi(h)==3 || HSV_Hi(h)==4 ? v                    : (\
     HSV_Hi(h)==5                 ? v*(1-HSV_f(h)*s)     : (\
     HSV_Hi(h)==2                 ? v*(1-(1-HSV_f(h))*s) : (\
     HSV_Hi(h)==0 || HSV_Hi(h)==1 ? v*(1-s)              : 0.0) )))
     
#HSV色空間のパラメータh,s,vをRGBの色を表す16進数文字列"#rrggbb"に変換する。
#3番目の引数の係数が200になっているのは、Greenを255にすると明るすぎて紙面上や画面上で見づらいため。
HSV2RGB(h,s,v)=sprintf("#%02x%02x%02x", 255*HSV2R(h,s,v), 200*HSV2G(h,s,v), 255*HSV2B(h,s,v))

#整数nをRGB文字列"#rrggbb"に変換する。
period=60.0   #グラデーションの周期(360で色が一周する)
start=0.0     #グラデーションをスタートする色。0ならn=0は赤に対応する。
num2color(n)=HSV2RGB(360.0*n/period+start, 1.0, 1.0)

HSV2RGB(h,s,v)という関数はHSV色空間のパラメータh,s,vをRGB空間の色を表す16進数文字列"#rrggbb"に変換します。ここで、hは任意の実数、svは0以上1以下の実数です。HSV2RGB(h,s,v)hに対しては360を周期とする周期関数です。

この変換関数を利用して、さらに整数nをRGB文字列に変換する関数num2color(n)を定義します。この関数はHSV空間のH(色相)を変化させます。2つのパラメータperiod(グラデーションの周期)とstart(グラデーションをスタートする色)を持ちます。それぞれ自分の好みに設定してください。色の変化を逆向き(赤→青→緑)にしたい場合はperiodを負の値にします。

実際にグラデーションを使う際は、plotwith ***の中でlinecolor rgb num2color(n)のようにこの関数を使用します。実行例を示します。

set angles degrees
set parametric
set samples 2
set trange [0:1]
a0=4.0
a1=10.0
set size ratio 1
set xrange [-15:15]
set yrange [-15:15]
plot for[n=0:60] (a0+a1*t)*cos(n/period*360.0),(a0+a1*t)*sin(n/period*360.0) \
     with lines linewidth 5 linecolor rgb num2color(n) title ""

先述の関数群を定義した後に上記のコードを実行する(gnuplot4.3以降が必要)と、以下のようなグラフが得られます。

ファイルをプロットする際は以下のようにperiodをプロットするファイルの総数よりやや多くして、plotの中でnをインクリメントするといいでしょう。(この例はgnuplot 4.2でも実行可)

period = 9.5  #priondはファイル数+0.5〜ファイル数+1程度にする
start  = 0

plot n=0,   "file0" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file1" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file2" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file3" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file4" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file5" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file6" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file7" w p pt 5 ps 2 lt 1 lc rgb num2color(n) ,\
     n=n+1, "file9" w p pt 5 ps 2 lt 1 lc rgb num2color(n)