Skip to content
10月 30 / rakkyoo

rubyでgnuplotを気軽に

以前、rubyを使ったgunuplotとして、以下のようにまとめたのですが、

もっと気軽にいろんなファイルをプロットしたいなと思い、気軽にrubyの配列などを流し込んでグラフにできるよう、自分用のグラフ化環境を整えて見ました。

作りたいグラフは、

  • 折れ線グラフのみ
  • 一画面に1つか2つのグラフ
  • 一つのグラフにいくつかの線を書きたい

っといったことのみに特化して、書いてみました。

作っておいたのは、以下のコード
たとえば、「gnuplot_func.rb」などとして保存しておいて、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# -*- coding: utf-8 -*-
class Gplot
  require 'gnuplot'
  attr_accessor :x, :y, :plot_attr, :filename, :legend
  def initialize(x = 0, y = 0, plot_attr={})
    @x = x
    @y = y
    @plot_attr = plot_attr
  end
 
  def plot_eps
    @plot_attr = attr_nil_check(@plot_attr)
    Gnuplot.open do |gp|
        Gnuplot::Plot.new( gp ) do |plot|
        plot.term "postscript 16 color"
        plot.output @filename
        plot.title  @plot_attr[:title]
        plot.ylabel @plot_attr[:ylabel]
        plot.xlabel @plot_attr[:xlabel]
        plot.xrange @plot_attr[:xrange]
        plot.yrange @plot_attr[:yrange]
        plot.bmargin "0"
 
        @y.size.times do |i|
          plot.data << Gnuplot::DataSet.new( [@x[i], @y[i]] ) do |ds|
            ds.with = @plot_attr[:with] # lines, points, lp:線と点, pt:ポイントの種類、ps:ポイントの大きさ
            ds.title = @legend[i] if @legend != nil
            ds.notitle if @legend == nil
            ds.linewidth = 4
          end
 
        end
        plot.grid
      end
    end
  end
  def attr_nil_check(plot_attr)
    plot_attr[:filename] = plot_attr[:filename] != nil ?  plot_attr[:filename] : "out.eps"
    plot_attr[:title] = plot_attr[:title] != nil ?  plot_attr[:title] : ""
    plot_attr[:xlabel] = plot_attr[:xlabel] != nil ?  plot_attr[:xlabel] : ""
    plot_attr[:ylabel] = plot_attr[:ylabel] != nil ?  plot_attr[:ylabel] : ""
    plot_attr[:xrange] = plot_attr[:xrange] != nil ?  plot_attr[:xrange] : "[*:*]"
    plot_attr[:yrange] = plot_attr[:yrange] != nil ?  plot_attr[:yrange] : "[*:*]"
    plot_attr[:with] = plot_attr[:with] != nil ?  plot_attr[:with] : "lp pt 7 ps 1"
    plot_attr
  end
end
 
class Gplot_multi_double
  require 'gnuplot'
  attr_accessor :x1, :y1, :plot_attr1, :x2, :y2, :plot_attr2, :filename, :legend1, :legend2
  def initialize(x1 = 0, x2 = 0, y1 = 0, y2 = 0, plot_attr1={}, plot_attr2={})
    # subplot1用
    @x1 = x1
    @y1 = y1
    @plot_attr1 = attr_nil_check(plot_attr1)
 
    # subplot2用
    @x2 = x2
    @y2 = y2
    @plot_attr2 = attr_nil_check(plot_attr2)
  end
 
  def plot_eps
    @plot_attr1 = attr_nil_check(@plot_attr1)
    @plot_attr2 = attr_nil_check(@plot_attr2)
    Gnuplot.open do |gp|
      Gnuplot::Plot.new( gp ) do |plot|
        plot.term "postscript 16 color"
        plot.output @filename
        plot.multiplot
        plot.title  @plot_attr1[:title]
        plot.ylabel @plot_attr1[:ylabel]
        plot.xlabel @plot_attr1[:xlabel]
        plot.xrange @plot_attr1[:xrange]
        plot.yrange @plot_attr1[:yrange]
        plot.size "1,0.35" #=> plotのサイズを決める
        plot.origin "0.0,0.55" #=> plot の原点位置
        plot.bmargin "1"
        plot.tmargin "0" #=> 上のマージンをなくす
 
        @y1.size.times do |i|
          plot.data << Gnuplot::DataSet.new( [@x1[i], @y1[i]] ) do |ds|
            ds.with = @plot_attr1[:with] # lines, points, lp:線と点, pt:ポイントの種類、ps:ポイントの大きさ
            ds.title = @legend1[i] if legend1 != nil
            ds.notitle if @legend1 == nil
            ds.linewidth = 4
          end
        end
        plot.grid
      end
 
      Gnuplot::Plot.new( gp ) do |plot|
        plot.multiplot
        plot.title  @plot_attr2[:title]
        plot.ylabel @plot_attr2[:ylabel]
        plot.xlabel @plot_attr2[:xlabel]
        plot.xrange @plot_attr2[:xrange]
        plot.yrange @plot_attr2[:yrange]
        plot.size "1,0.35" #=> plotのサイズを決める
        plot.origin "0.0,0.1" #=> plot の原点位置
        plot.bmargin "0" #=> 下のマージンをなくす
        plot.tmargin "1"
 
        @y2.size.times do |i|
          plot.data << Gnuplot::DataSet.new( [@x2[i], @y2[i]] ) do |ds|
            ds.with = @plot_attr2[:with] # lines, points, lp:線と点, pt:ポイントの種類、ps:ポイントの大きさ
            ds.title = @legend2[i] if legend2 != nil
            ds.notitle if @legend2 == nil
            ds.linewidth = 4
          end
        end
        plot.grid
      end
    end
  end
 
  def attr_nil_check(plot_attr)
    plot_attr[:title] = plot_attr[:title] != nil ?  plot_attr[:title] : ""
    plot_attr[:xlabel] = plot_attr[:xlabel] != nil ?  plot_attr[:xlabel] : ""
    plot_attr[:ylabel] = plot_attr[:ylabel] != nil ?  plot_attr[:ylabel] : ""
    plot_attr[:xrange] = plot_attr[:xrange] != nil ?  plot_attr[:xrange] : "[*:*]"
    plot_attr[:yrange] = plot_attr[:yrange] != nil ?  plot_attr[:yrange] : "[*:*]"
    plot_attr[:with] = plot_attr[:with] != nil ?  plot_attr[:with] : "lp pt 7 ps 1"
    plot_attr
  end
end

以下のように、

1
require "./gnuplot_func"

作成した「gnuplot_func.rb」を呼び出して使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# -*- coding: utf-8 -*-
 
require "gnuplot"
require "./gnuplot_func"
 
# データ配列の作成
x1 = (-100..100).map {|v| v.to_f+50}
y1 = (-100..100).map {|v| v.to_f ** 2}
 
x2 = (-100..100).map {|v| v.to_f+100}
y2 = (-100..100).map {|v| v.to_f ** 2}
 
x3 = (-100..100).map {|v| v.to_f-50}
y3 = (-100..100).map {|v| v.to_f ** 2}
 
# グラフ化
a = Gplot.new
a.filename = "out.eps" # ファイル名の指定
a.x = [x1, x2, x3] # x軸に相当する配列群の指定
a.y = [y1, y2, y3] # y軸に相当する配列群の指定
a.legend = ["test1", "test2", "test3"] # 各線の名前
a.plot_attr = {title: "plots", xlabel: "xlabel", ylabel: "ylabel"} # グラフ用の設定項目
a.plot_eps # グラフ化してEPSファイルに出力

そうすると、以下のようなファイルができます。

Out pdf 1 ページ

ちなみに、xの範囲やyの範囲については、xrangeとyrangeで指定してもよく、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# -*- coding: utf-8 -*-
 
require "gnuplot"
require "./gnuplot_func"
 
# データ配列の作成
x1 = (-100..100).map {|v| v.to_f+50}
y1 = (-100..100).map {|v| v.to_f ** 2}
 
x2 = (-100..100).map {|v| v.to_f+100}
y2 = (-100..100).map {|v| v.to_f ** 2}
 
x3 = (-100..100).map {|v| v.to_f-50}
y3 = (-100..100).map {|v| v.to_f ** 2}
 
# グラフ化
a = Gplot.new
a.filename = "out.eps" # ファイル名の指定
a.x = [x1, x2, x3] # x軸に相当する配列群の指定
a.y = [y1, y2, y3] # y軸に相当する配列群の指定
a.legend = ["test1", "test2", "test3"] # 各線の名前
a.plot_attr = {title: "plots", xlabel: "xlabel", ylabel: "ylabel"} # グラフ用の設定項目
a.plot_attr[:xrange] = "[-50:50]" # xrangeの指定
a.plot_attr[:yrange] = "[0:4000]" # yrangeの指定
a.plot_eps # グラフ化してEPSファイルに出力

こんな感じになります。
Out pdf 1 ページ

線種などを変更する時は、「with」を指定すればよく、

1
a.with = "lp pt 7 ps 1"

などと指定します。
線種の指定方法などは、以下のサイトなどを参考に指定すればOKです。

つづいて、同様に一画面で二つのグラフを出したい場合については、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-
 
require "gnuplot"
require "./gnuplot_func"
 
# データ配列の作成
x1 = (-100..100).map {|v| v.to_f+50}
y1 = (-100..100).map {|v| v.to_f ** 2}
 
x2 = (-100..100).map {|v| v.to_f+100}
y2 = (-100..100).map {|v| v.to_f ** 2}
 
x3 = (-100..100).map {|v| v.to_f-50}
y3 = (-100..100).map {|v| v.to_f ** 2}
 
# グラフ化
a = Gplot_multi_double.new
a.filename = "out.eps"
a.x1 = [x1, x2, x3]
a.y1 = [y1, y2, y3]
a.legend1 = ["test1", "test2", "test3"]
a.plot_attr1 = {title: "plot123", xlabel: "xlabel", ylabel: "ylabel"}
 
a.x2 = [x2, x3, x1]
a.x2 = [y2, y3, y1]
a.x2 = a.x1
a.y2 = a.y1
a.legend2 = ["test2", "test3", "test1"]
a.plot_attr2 = {title: "plot231", xlabel: "xlabel", ylabel: "ylabel"}
a.plot_eps

こんな感じに、Gplot_multi_doubleに対して、x1,y1,legend1,plot_attr1と、x2,y2,legend2,plot_attr2を個別に設定すればいいだけです。
Out pdf 1 ページ

簡単なクラスを用意しておくだけで、とっても簡単にグラフ化できるようになりました。

とっても快適に。

[`twib` not found]

Leave a comment

CAPTCHA


This blog is kept spam free by WP-SpamFree.