Edited at

Gnuplotを使ってGIF生成

More than 1 year has passed since last update.


引き続き、ヴィジュアライズしたい。

RMagickを使ってGIF生成


ビジュアライズに限れば適当なplotを使えば良いのだろうけど、gifも欲しい。


どうもその適当なplotで十分GIF生成もできる様なのでお試し。


Gnuplot

ruby bindingがgemにあるのでinstall.

サンプルはあるがドキュメントは無いせいか、イマイチ使いにくい。

ソースを見てみるとやってることはシンプルで、薄いラッパー。

gnuplotコマンドに文字列を流し込んでいるだけ。

set term gif animateと相性が悪いだけで、他の用途なら問題無い気もする。


make_gif

set term gif animateとして、output先のファイル設定して、plotを繰り返せばアニメーションGIFに。


gnuplot_make_gif.rb

require "gnuplot"

def make_gif(name = "",x = 0,y = 0,fps = 0, &f)
Gnuplot.open { |g|
g << "set nokey\n"
g << "set term gif animate\n"
g << "set output \"#{name}\"\n"
g << "set xrange [-1:#{x+1}]\n"
g << "set yrange [-1:#{y+1}]\n"
g << "set style line 1 lc \"green\" pt 7 ps 1\n"

(1..fps).each { |n|
cs = f.call(g,n)
g << "plot \"-\" with points ls 1\n#{cs}"
}
}
end



lifegame

plotに渡すデータへ二次元配列を変換。ちょいめんどい。

require "./gnuplot_make_gif.rb"

require "./lifegame.rb"

lg = Lifegame.new(300,300)
lg.random

make_gif("gnuplot_lifegame.gif",300,300,100) { |io,n|
io << "set style line 1 lc \"green\" pt 7 ps 0.25\n"
io << "set title \"lifegame:#{n}\"\n"
cs = lg.cells.map.with_index { |cy,iy|
cy.map.with_index { |cx,ix|
if cx == 1
"#{ix} #{iy}"
else
nil
end
}.select { |a| a != nil }.join("\n")
}.join("\n")
cs << "\ne\n"
lg.apply
cs
}

gnuplot_lifegame.gif


end

この300*300*100のGIF生成に、私のPCでは70秒ほどかかります。

座標変換のコストがちょいかかってます。