grada 1.1.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/lib/grada/gnuplot.rb +226 -0
  2. data/lib/grada.rb +32 -32
  3. metadata +2 -17
@@ -0,0 +1,226 @@
1
+ require 'matrix'
2
+
3
+ class NoGnuPlotExecutableFound < RuntimeError; end
4
+
5
+ class Gnuplot
6
+ def self.candidate?(candidate)
7
+ return candidate if File::executable? candidate
8
+
9
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
10
+ possible_candidate = File::join dir, candidate.strip
11
+
12
+ return possible_candidate if File::executable? possible_candidate
13
+ end
14
+
15
+ nil
16
+ end
17
+
18
+ def self.find_exec(bin)
19
+ bin_list = RUBY_PLATFORM =~ /mswin|mingw/ ? [bin, "#{bin}.exe"] : [bin]
20
+
21
+ bin_list.each do |c|
22
+ exec = candidate?(c)
23
+ return exec if exec
24
+ end
25
+
26
+ nil
27
+ end
28
+
29
+ def self.gnuplot(persist)
30
+ gnu_exec = find_exec( ENV['RB_GNUPLOT'] || 'gnuplot' )
31
+
32
+ raise NoGnuPlotExecutableFound unless gnu_exec
33
+
34
+ "#{gnu_exec} #{'-persist' if persist}"
35
+ end
36
+
37
+ def self.open(persist = true)
38
+ output = nil
39
+ gnuplot_cmd = gnuplot(persist)
40
+
41
+ IO::popen( gnuplot_cmd, 'w+' ) do |io|
42
+ yield io
43
+ io.close_write
44
+ output = io.read
45
+ end
46
+
47
+ output
48
+ end
49
+ end
50
+
51
+ class Plot
52
+ attr_accessor :cmd, :data, :settings, :arbitrary_lines
53
+
54
+ QUOTED_METHODS = [ "title", "output", "xlabel", "x2label", "ylabel", "y2label", "clabel", "cblabel", "zlabel" ]
55
+
56
+ def initialize(io = nil, cmd = 'plot')
57
+ @cmd = cmd
58
+ @settings = []
59
+ @arbitrary_lines = []
60
+ @data = []
61
+ @styles = []
62
+ yield self if block_given?
63
+
64
+ if io
65
+ io << to_gplot
66
+ io << store_datasets
67
+ end
68
+ end
69
+
70
+ def method_missing(meth, *args)
71
+ set meth.id2name, *args
72
+ end
73
+
74
+ def set ( var, value = "" )
75
+ value = "\"#{value}\"" if QUOTED_METHODS.include? var unless value =~ /^'.*'$/
76
+ @settings << [ :set, var, value ]
77
+ end
78
+
79
+ def unset (var)
80
+ @settings << [ :unset, var ]
81
+ end
82
+
83
+ def to_gplot(io = '')
84
+ @settings.each { |setting| io += setting.map(&:to_s).join(' ') + "\n" }
85
+ @styles.each{ |style| io += style.to_s + "\n" }
86
+ @arbitrary_lines.each{ |line| io += line + "\n" }
87
+
88
+ io
89
+ end
90
+
91
+ def store_datasets(io = '')
92
+ if @data.size > 0
93
+ io += @cmd + " #{ @data.map { |element| element.plot_args }.join(', ') } \n"
94
+ io += @data.map { |ds| ds.to_gplot }.compact.join("e\n")
95
+ end
96
+
97
+ io
98
+ end
99
+
100
+ def style(&blk)
101
+ @styles << Style.new(&blk)
102
+ end
103
+
104
+ class Style
105
+ attr_accessor :linestyle, :linetype, :linewidth, :linecolor, :pointtype, :pointsize, :fill, :index
106
+
107
+ alias :ls :linestyle
108
+ alias :lt :linetype
109
+ alias :lw :linewidth
110
+ alias :lc :linecolor
111
+ alias :pt :pointtype
112
+ alias :ps :pointsize
113
+ alias :fs :fill
114
+
115
+ STYLES = [:ls, :lt, :lw, :lc, :pt, :ps, :fs]
116
+
117
+ def self.increment_index
118
+ @index ||= 0
119
+ @index += 1
120
+ end
121
+
122
+ def initialize
123
+ STYLES.each do |style|
124
+ send("#{style}=", nil)
125
+ end
126
+
127
+ yield self if block_given?
128
+
129
+ self.increment_index
130
+ end
131
+
132
+ def to_s
133
+ str = "set style line #{@index}"
134
+
135
+ STYLES.each do |style|
136
+ str += " #{send(style)} #{style}" if send(style)
137
+ end
138
+
139
+ str
140
+ end
141
+ end
142
+ end
143
+
144
+ class DataSet
145
+ attr_accessor :title, :with, :using, :data, :linewidth, :linecolor, :matrix, :smooth, :axes, :index, :linestyle
146
+
147
+ alias :ls :linestyle
148
+
149
+ def initialize(data = nil)
150
+ @data = data
151
+ @linestyle = nil
152
+ @title = nil
153
+ @with = nil
154
+ @using = nil
155
+ @linewidth = nil
156
+ @linecolor = nil
157
+ @matrix = nil
158
+ @smooth = nil
159
+ @axes = nil
160
+ @index = nil
161
+
162
+ yield self if block_given?
163
+ end
164
+
165
+ def notitle
166
+ '"No Title"'
167
+ end
168
+
169
+ def plot_args(io = '')
170
+ io += @data.is_a?(String) ? @data : "'-'"
171
+ io += " index #{@index}" if @index
172
+ io += " using #{@using}" if @using
173
+ io += " axes #{@axes}" if @axes
174
+ io += " title #{@title ? "\"#{@title}\"" : notitle}"
175
+ io += " matrix #{@matrix}" if @matrix
176
+ io += " smooth #{@smooth}" if @smooth
177
+ io += " with #{@with}" if @with
178
+ io += " linecolor #{@linecolor}" if @linecolor
179
+ io += " linewidth #{@linewidth}" if @linewidth
180
+ io += " linestyle #{@linestyle.index}" if @linestyle
181
+
182
+ io
183
+ end
184
+
185
+ def to_gplot
186
+ return nil if @data.nil? || @data.is_a?(String)
187
+
188
+ @data.to_gplot
189
+ end
190
+ end
191
+
192
+ class Array
193
+ def to_gplot
194
+ if number_series?(self)
195
+ series_for_plot = ''
196
+ self.each { |elem| series_for_plot += "#{elem}\n" }
197
+ series_for_plot + 'e'
198
+ else
199
+ self[0].zip(self[1]).map{ |elem| elem.join(' ') }.join("\n") + "\ne"
200
+ end
201
+ end
202
+
203
+ private
204
+
205
+ def number_series?(data)
206
+ data.each do |elem|
207
+ return false unless elem.is_a?(Numeric)
208
+ end
209
+
210
+ true
211
+ end
212
+ end
213
+
214
+ class Matrix
215
+ def to_gplot
216
+ matrix_for_plot = ''
217
+
218
+ (0...self.column_size).each do |j|
219
+ (0...self.row_size).each do |i|
220
+ matrix_for_plot += "#{i} #{j} #{self[j,i]}\n" if self[j,i]
221
+ end
222
+ end
223
+
224
+ matrix_for_plot
225
+ end
226
+ end
data/lib/grada.rb CHANGED
@@ -1,23 +1,23 @@
1
- require 'gnuplot'
1
+ require 'grada/gnuplot'
2
2
 
3
3
  class Grada
4
4
  # Not valid the format of the object to construct the graph
5
5
  #
6
6
  class NotValidArrayError < RuntimeError; end
7
-
7
+
8
8
  # Not valid the content of the array you're passing to build the graph
9
9
  #
10
10
  class NotValidDataError < RuntimeError; end
11
-
11
+
12
12
  # Can't build the plot
13
13
  #
14
14
  class NoPlotDataError < RuntimeError; end
15
-
15
+
16
16
  attr_reader :x
17
17
  attr_reader :y
18
-
19
- DEFAULT_OPTIONS = {width: 1600,
20
- height: 400,
18
+
19
+ DEFAULT_OPTIONS = {width: 1920,
20
+ height: 1080,
21
21
  title: "Graph",
22
22
  x_label: "X",
23
23
  y_label: "Y",
@@ -26,7 +26,7 @@ class Grada
26
26
 
27
27
  # Hello GraDA
28
28
  #
29
-
29
+
30
30
  def self.hi
31
31
  puts "Hello GraDA"
32
32
  end
@@ -45,11 +45,10 @@ class Grada
45
45
  # y: (Array) *optional*
46
46
 
47
47
  def initialize(x, y = nil)
48
-
49
48
  @x = validate(x)
50
49
  @y = y.nil? ? y : validate(y)
51
50
  end
52
-
51
+
53
52
  # Displays a graph in a window.
54
53
  # You can specify all the options that you need:
55
54
  # *width* (Integer)
@@ -68,7 +67,7 @@ class Grada
68
67
  # => ""
69
68
  # Arguments:
70
69
  # opts: (Hash) *optional*
71
-
70
+
72
71
  def display(opts = {})
73
72
  @opts = DEFAULT_OPTIONS.merge(opts)
74
73
 
@@ -91,7 +90,7 @@ class Grada
91
90
  end
92
91
  end
93
92
  end
94
-
93
+
95
94
  # Save the graph in a png file.
96
95
  # You can specify all the options that you need as _display_ but also need to specify the file
97
96
  #
@@ -111,7 +110,7 @@ class Grada
111
110
 
112
111
  plot_histogram do |plot|
113
112
  plot.output @opts[:filename]
114
- plot.set "terminal x11 size #{@opts[:width]},#{@opts[:height]}"
113
+ plot.set "terminal png size #{@opts[:width]}, #{@opts[:height]} crop"
115
114
  plot.terminal 'png'
116
115
  end
117
116
  elsif @opts[:graph_type] == :heatmap
@@ -120,6 +119,7 @@ class Grada
120
119
 
121
120
  plot_heat_map do |plot|
122
121
  plot.output @opts[:filename]
122
+ plot.set "terminal png size #{@opts[:width]}, #{@opts[:height]} crop"
123
123
  plot.terminal 'png'
124
124
  end
125
125
  else
@@ -127,7 +127,7 @@ class Grada
127
127
 
128
128
  plot_and do |plot|
129
129
  plot.output @opts[:filename]
130
- plot.set "terminal x11 size #{@opts[:width]*10},#{@opts[:height]}"
130
+ plot.set "terminal png size #{@opts[:width]}, #{@opts[:height]} crop"
131
131
  plot.terminal 'png'
132
132
  end
133
133
  end
@@ -137,7 +137,7 @@ class Grada
137
137
 
138
138
  def validate(l)
139
139
  raise NotValidArrayError if ! l.is_a?(Array)
140
-
140
+
141
141
  l.each do |elem|
142
142
  raise NotValidDataError if ! ( elem.is_a?(Float) || elem.is_a?(Integer) || elem.is_a?(Array) || elem.is_a?(Hash))
143
143
  end
@@ -145,7 +145,7 @@ class Grada
145
145
 
146
146
  def population_data?(l)
147
147
  raise NotValidArrayError if ! l.is_a?(Array)
148
-
148
+
149
149
  l.each do |elem|
150
150
  raise NotValidDataError if ! ( elem.is_a?(Float) || elem.is_a?(Integer))
151
151
  end
@@ -156,7 +156,7 @@ class Grada
156
156
  l.each do |elem|
157
157
  return false if ! elem.is_a?(Hash)
158
158
  end
159
-
159
+
160
160
  return true
161
161
  end
162
162
 
@@ -164,22 +164,22 @@ class Grada
164
164
  end
165
165
 
166
166
  def plot_and(&block)
167
- ::Gnuplot.open do |gp|
168
- ::Gnuplot::Plot.new(gp) do |plot|
167
+ Gnuplot.open do |gp|
168
+ Gnuplot::Plot.new(gp) do |plot|
169
169
  block[plot] if block
170
-
170
+
171
171
  plot.title @opts[:title]
172
172
 
173
173
  plot.xlabel @opts[:x_label]
174
174
  plot.ylabel @opts[:y_label]
175
-
175
+
176
176
  if multiple_data?(@y)
177
177
  @y.each do |dic|
178
178
  dic.each do |k, v|
179
179
  if k.to_sym != :with
180
180
  raise NoPlotDataError if ! v.nil? && @x.size != v.size
181
181
 
182
- plot.data << ::Gnuplot::DataSet.new([@x,v]) do |ds|
182
+ plot.data << Gnuplot::DataSet.new([@x,v]) do |ds|
183
183
  ds.with = dic[:with] || @opts[:with]
184
184
  ds.title = "#{k}"
185
185
  end
@@ -189,7 +189,7 @@ class Grada
189
189
  else
190
190
  raise NoPlotDataError if ! @y.nil? && @x.size != @y.size
191
191
 
192
- plot.data << ::Gnuplot::DataSet.new([@x,@y]) do |ds|
192
+ plot.data << Gnuplot::DataSet.new([@x,@y]) do |ds|
193
193
  ds.with = @opts[:with]
194
194
  end
195
195
  end
@@ -198,19 +198,19 @@ class Grada
198
198
  end
199
199
 
200
200
  def plot_histogram(&block)
201
- ::Gnuplot.open do |gp|
202
- ::Gnuplot::Plot.new(gp) do |plot|
201
+ Gnuplot.open do |gp|
202
+ Gnuplot::Plot.new(gp) do |plot|
203
203
  block[plot] if block
204
-
204
+
205
205
  plot.title @opts[:title]
206
206
 
207
207
  plot.set "style data histogram"
208
208
  plot.xlabel @opts[:x_label]
209
209
  plot.ylabel "Frecuency"
210
-
210
+
211
211
  x = @x.sort.group_by { |xi| xi }.map{|k,v| v.count }
212
212
 
213
- plot.data << ::Gnuplot::DataSet.new(x) do |ds|
213
+ plot.data << Gnuplot::DataSet.new(x) do |ds|
214
214
  ds.with = @opts[:with]
215
215
  end
216
216
  end
@@ -218,8 +218,8 @@ class Grada
218
218
  end
219
219
 
220
220
  def plot_heat_map(&block)
221
- ::Gnuplot.open do |gp|
222
- ::Gnuplot::Plot.new(gp) do |plot|
221
+ Gnuplot.open do |gp|
222
+ Gnuplot::Plot.new(gp) do |plot|
223
223
  block[plot] if block
224
224
 
225
225
  plot.set "pm3d map"
@@ -232,9 +232,9 @@ class Grada
232
232
  plot.set "palette define"
233
233
 
234
234
  plot.title @opts[:title]
235
- plot.data = [::Gnuplot::DataSet.new(Matrix.columns(@x)) do |ds|
235
+ plot.data << Gnuplot::DataSet.new(Matrix.columns(@x)) do |ds|
236
236
  ds.with = @opts[:with]
237
- end]
237
+ end
238
238
  end
239
239
  end
240
240
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grada
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -43,22 +43,6 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
- - !ruby/object:Gem::Dependency
47
- name: gnuplot
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: 2.6.2
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: 2.6.2
62
46
  description: Graphic Data Analysis gem
63
47
  email: hard_rock15@msn.com
64
48
  executables: []
@@ -66,6 +50,7 @@ extensions: []
66
50
  extra_rdoc_files: []
67
51
  files:
68
52
  - lib/grada.rb
53
+ - lib/grada/gnuplot.rb
69
54
  homepage: https://github.com/emfigo/grada
70
55
  licenses: []
71
56
  post_install_message: