GnuplotをRubyから操作

C#から操作するのはこのブログで昔に扱ったったように思うけれど、最近はずっとUnix環境下なのでRubyで。
RubyでOpen3というのを使うと、Ruby内で外部プログラムを起動してその標準入力、標準出力、標準エラー出力を扱うことができる。

例えばアニメーションの作成

#!/usr/bin/ruby

require 'open3'

Open3.popen3('gnuplot') do |gp_in, gp_out, gp_err|

  Signal.trap(:INT) do
    gp_in.close
    print gp_err.read
    exit
  end
  
  gp_in.puts "set terminal gif animate delay 2 optimize size 640, 480"
  
  gp_in.puts "set output \"pic.gif\""

  PhaseSplitCount = 128
  TWO_PI = 3.141592 * 2
  
  for i in 0..(PhaseSplitCount-1)
    gp_in.puts "plot sin(x+#{i*TWO_PI/PhaseSplitCount})"

    gp_in.puts "print \"#{i}\""
    puts gp_err.gets
  end

  gp_in.puts "set output"
  gp_in.puts "exit"
  
  gp_in.close
end

これをすると正弦波が移動していくアニメができる。
途中の

gp_in.puts "print \"#{i}\""
puts gp_err.gets

は何をしているかというと、gnuplotにコンソール出力をさせ、それを読み取るまでRuby側で待つということをして、同期をはかっている。別に非同期でよければ無くてもよいのだが、アニメーション作成時だったらどのコマまで描画したかというのは知りたいものであろう。
あと

Signal.trap(:INT)

のくだりは、Ctrl+Cで強制終了させられるときには、その前にgnuplotのパイプを閉じるようにしている。そうしないと終了しないからだ。