numo-gnuplot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7a5482f076a126f3270d221c2ad38455ac266b6a
4
+ data.tar.gz: 1115269a4c0e558c2272f14b36e591e41d26bd28
5
+ SHA512:
6
+ metadata.gz: 0cb38d93f404dca82818117ae8f7620c160bbd3eb3e6f3abfcf3a2d9cd44b05d2d3a445b6f2592b6011446fd7038a0da6f4660131a659c1cefb976484e0f5161
7
+ data.tar.gz: 76b7602cd0fe6f0e23e5a62dddc01ff63cf5064ad54a5bf8a3d8594dfcec9d600990a81dc539c72cfc490ad0b3913220f1214ca70b94f734a4e1286b3c7a0742
@@ -0,0 +1,54 @@
1
+ *.gem
2
+ *.rbc
3
+ Gemfile.lock
4
+ InstalledFiles
5
+ SetupConfig
6
+ SetupReceipt
7
+ coverage
8
+ pkg/
9
+ spec/reports
10
+ spec/examples.txt
11
+ spec/*/*.dat
12
+ spec/*/*.csv
13
+ test/tmp
14
+ test/version_tmp
15
+ tmp/
16
+ .config
17
+ *~
18
+ */*~
19
+ */*/*~
20
+ *.bak
21
+ */*.bak
22
+ */*/*.bak
23
+ .#*
24
+ */.#*
25
+ */*/.#*
26
+ rhosts
27
+
28
+ ## Specific to RubyMotion:
29
+ .dat*
30
+ .repl_history
31
+ build/
32
+
33
+ ## Documentation cache and generated files:
34
+ .yardoc/
35
+ _yardoc/
36
+ doc/
37
+ rdoc/
38
+
39
+ ## Environment normalization:
40
+ .bundle/
41
+ /vendor/bundle
42
+ /lib/bundler/man/
43
+
44
+ # for a library or gem, you might want to ignore these files since the code is
45
+ # intended to run in multiple environments; otherwise, check them in:
46
+ # Gemfile.lock
47
+ # .ruby-version
48
+ # .ruby-gemset
49
+
50
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
51
+ .rvmrc
52
+
53
+ # examples
54
+ /examples/*.png
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in numo-gnuplot.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Masahiro TANAKA
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,153 @@
1
+ # Numo::Gnuplot : Gnuplot interface for Ruby
2
+
3
+ * Alpha version under development.
4
+ * [GitHub site](https://github.com/masa16/numo-gnuplot)
5
+
6
+ Although there are many [other Gnuplot interface libraries for Ruby](https://github.com/masa16/numo-gnuplot#related-work),
7
+ none of them have so simple interface as to obtain an XY data plot by just typing:
8
+
9
+ plot x,y
10
+
11
+ Numo::Gnuplot achieves this by providing only one class which has
12
+ the same inteface as Gnuplot command line, and no other class which
13
+ causes extra learning costs.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'numo-gnuplot'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install numo-gnuplot
30
+
31
+ ## Usage
32
+
33
+ * All examples require to load Numo::Gnuplot class:
34
+
35
+ ```ruby
36
+ require "numo/gnuplot"
37
+ ```
38
+
39
+ * The first example showing how it works.
40
+
41
+ ```ruby
42
+ gp = Numo::Gnuplot.new
43
+ gp.set title:"First Example"
44
+ gp.plot "sin(x)"
45
+ ```
46
+
47
+ * You can avoid receiver.
48
+
49
+ ```ruby
50
+ Numo::Gnuplot.new.instance_eval do
51
+ set title:"Second Example"
52
+ plot "sin(x)"
53
+ end
54
+ ```
55
+
56
+ * The same thing in short.
57
+
58
+ ```ruby
59
+ Numo.gnuplot do
60
+ set title:"Third Example"
61
+ plot "sin(x)"
62
+ end
63
+ ```
64
+
65
+ * Interactive plotting with IRB:
66
+
67
+ ```
68
+ $ irb -r numo/gnuplot
69
+ irb(main):001:0> pushb Numo.gnuplot
70
+ irb(gnuplot):002:0> set t:"Forth Example"
71
+ irb(gnuplot):003:0> plot "sin(x)"
72
+ ```
73
+
74
+ * Plotting X-Y data.
75
+
76
+ ```ruby
77
+ require "numo/gnuplot"
78
+
79
+ x = (0..100).map{|i| i*0.1}
80
+ y = x.map{|i| Math.sin(i)}
81
+
82
+ Numo.gnuplot do
83
+ set title:"X-Y data plot"
84
+ plot x,y, w:'lines', t:'sin(x)'
85
+ end
86
+ ```
87
+
88
+ * Plotting X-Y data in NArray.
89
+
90
+ ```ruby
91
+ require "numo/gnuplot"
92
+ require "numo/narray"
93
+
94
+ x = Numo::DFloat[0..100]/10
95
+ y = Numo::NMath.sin(x)
96
+
97
+ Numo.gnuplot do
98
+ set title:"X-Y data plot in Numo::NArray"
99
+ plot x,y, w:'lines', t:'sin(x)'
100
+ end
101
+ ```
102
+
103
+ * Multiple data are separated by Hash or put into Array.
104
+
105
+ ```ruby
106
+ require 'numo/gnuplot'
107
+ require 'numo/narray'
108
+ NM = Numo::NMath
109
+
110
+ n = 60
111
+ x = Numo::DFloat[-n..n]/n*10
112
+
113
+ Numo.gnuplot do
114
+ set title:"multiple data series"
115
+ # separate by Hash
116
+ plot x,NM.sin(x), {w:'points',t:'sin(x)'}, x,x*NM.sin(x),{w:"lines",t:'x*sin(x)'}
117
+ # or separate into Array
118
+ # plot [x,NM.sin(x), w:'points',t:'sin(x)'], [x,x*NM.sin(x),w:"lines",t:'x*sin(x)']
119
+ # (here last item in each Array should be Hash in order to distinguish from array data)
120
+ gets
121
+ end
122
+ ```
123
+
124
+ * Plotting 2D arrays in 3D.
125
+
126
+ ```ruby
127
+ require 'numo/gnuplot'
128
+ require 'numo/narray'
129
+
130
+ n = 60
131
+ x = (Numo::DFloat.new(1,n).seq/n-0.5)*30
132
+ y = (Numo::DFloat.new(n,1).seq/n-0.5)*30
133
+ r = Numo::NMath.sqrt(x**2+y**2) + 1e-10
134
+ z = Numo::NMath.sin(r)/r
135
+
136
+ Numo.gnuplot do
137
+ set title:'2D data plot'
138
+ set dgrid3d:[60,60]
139
+ splot z, w:'pm3d', t:'sin(r)/r'
140
+ end
141
+ ```
142
+
143
+ ## Related Work
144
+
145
+ * [Ruby Gnuplot](https://github.com/rdp/ruby_gnuplot/tree/master)
146
+ * [GNUPlotr](https://github.com/pbosetti/gnuplotr)
147
+ * [GnuPlotter](https://github.com/maasha/gnuplotter)
148
+ * [GnuplotRB](https://github.com/dilcom/gnuplotrb)
149
+
150
+ ## Contributing
151
+
152
+ Bug reports and pull requests are welcome on GitHub at
153
+ https://github.com/[USERNAME]/numo-gnuplot.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1,20 @@
1
+ require "numo/gnuplot"
2
+
3
+ gp = Numo.gnuplot
4
+
5
+ puts "mouse/key on window to continue"
6
+ Dir.glob("ex*.rb") do |frb|
7
+ gp.reset
8
+ load frb
9
+ gp.pause mouse:"any"
10
+ end
11
+
12
+ gp.set term:"png"
13
+
14
+ Dir.glob("ex*.rb") do |frb|
15
+ fimg = File.basename(frb,".rb")+".png"
16
+ gp.reset
17
+ gp.set output:fimg
18
+ load frb
19
+ puts "wrote #{fimg}"
20
+ end
@@ -0,0 +1,7 @@
1
+ Numo.gnuplot do
2
+ set xrange:-5..10
3
+ set title:'Math function example'
4
+ set xlabel:'x'
5
+ set ylabel:'y'
6
+ plot 'x*sin(x)', with:'lines', lt:{rgb:'blue',lw:3}
7
+ end
@@ -0,0 +1,11 @@
1
+ # X-Y data plot
2
+
3
+ x = 20.times.map{|i| i*0.5}
4
+ y = x.map{|i| i*Math.sin(i)}
5
+
6
+ Numo.gnuplot do
7
+ set title:'X-Y data plot example'
8
+ set xlabel:'x'
9
+ set ylabel:'y'
10
+ plot x,y, with:'lp', lt:{rgb:'blue',lw:3}
11
+ end
@@ -0,0 +1,10 @@
1
+ require 'numo/narray'
2
+
3
+ # X-Y data plot with Numo::NArray
4
+ x = Numo::DFloat[0..100]/10
5
+ y = Numo::NMath.sin(x)
6
+
7
+ Numo.gnuplot do
8
+ set title:"X-Y data plot with Numo::NArray"
9
+ plot x,y, w:'lines', t:'sin(x)'
10
+ end
@@ -0,0 +1,6 @@
1
+ # multiple function plot (Array separated)
2
+
3
+ Numo.gnuplot do
4
+ set title:"Multiple function plot"
5
+ plot ['sin(x)', w:"lp"],['x*sin(x)',w:"lines"]
6
+ end
@@ -0,0 +1,11 @@
1
+ require 'numo/narray'
2
+
3
+ # multiple data series plot (Hash separated)
4
+ n = 60
5
+ x = Numo::DFloat[-n..n]/n*10
6
+ nm = Numo::NMath
7
+
8
+ Numo.gnuplot do
9
+ set title:"multiple data series plot"
10
+ plot x,nm.sin(x), {w:'points',t:'sin(x)'}, x,x*nm.sin(x),{w:"lines",t:'x*sin(x)'}
11
+ end
@@ -0,0 +1,14 @@
1
+ require "numo/narray"
2
+
3
+ # 3D plot of 2D data with Numo::NArray
4
+ n = 60
5
+ x = (Numo::DFloat.new(1,n).seq/n-0.5)*30
6
+ y = (Numo::DFloat.new(n,1).seq/n-0.5)*30
7
+ r = Numo::NMath.sqrt(x**2+y**2) + 1e-10
8
+ z = Numo::NMath.sin(r)/r
9
+
10
+ Numo.gnuplot do
11
+ set title:'3D plot of 2D data'
12
+ set dgrid3d:[60,60]
13
+ splot z, w:'pm3d', t:'sin(r)/r'
14
+ end
@@ -0,0 +1,22 @@
1
+ require "numo/narray"
2
+
3
+ # 3D plot of XYZ data with Numo::NArray
4
+ df = Numo::DFloat
5
+ nm = Numo::NMath
6
+ n = 120
7
+ x = (df.new(1,n).seq/n-0.5)*30
8
+ y = (df.new(n,1).seq/n-0.5)*30
9
+ r = nm.sqrt(x**2+y**2) + 1e-10
10
+ z = nm.sin(r)/r
11
+ x += df.zeros(n,1)
12
+ y += df.zeros(1,n)
13
+
14
+ Numo.gnuplot do
15
+ set title:'3D plot of XYZ data',
16
+ palette:{rgbformula:[22,13,-31]},
17
+ dgrid3d:[60,60],
18
+ xlabel:'x',
19
+ ylabel:'y',
20
+ zlabel:'sin(r)/r'
21
+ splot x,y,z, w:'pm3d', t:'sin(r)/r'
22
+ end
@@ -0,0 +1,493 @@
1
+ module Numo
2
+
3
+ def gnuplot(&block)
4
+ if block
5
+ Gnuplot.default.instance_eval(&block)
6
+ else
7
+ Gnuplot.default
8
+ end
9
+ end
10
+ module_function :gnuplot
11
+
12
+ class Gnuplot
13
+
14
+ VERSION = "0.1.0"
15
+ POOL = []
16
+ DATA_FORMAT = "%.5g"
17
+
18
+ class GnuplotError < StandardError; end
19
+
20
+ def self.default
21
+ POOL[0] ||= self.new
22
+ end
23
+
24
+ def initialize(gnuplot_command="gnuplot")
25
+ @history = []
26
+ @iow = IO.popen(gnuplot_command+" 2>&1","w+")
27
+ @ior = @iow
28
+ @gnuplot_version = send_cmd("print GPVAL_VERSION")[0].chomp
29
+ @debug = false
30
+ end
31
+
32
+ attr_reader :history
33
+ attr_reader :gnuplot_version
34
+
35
+ # draw 2D functions and data.
36
+ def plot(*args)
37
+ _plot_splot("plot",args)
38
+ nil
39
+ end
40
+
41
+ # draws 2D projections of 3D surfaces and data.
42
+ def splot(*args)
43
+ _plot_splot("splot",args)
44
+ nil
45
+ end
46
+
47
+ def _plot_splot(cmd,args)
48
+ contents = parse_plot_args(args)
49
+ r = contents.shift.map{|x|"[#{x.begin}:#{x.end}] "}.join
50
+ c = contents.map{|x| x.cmd_str}.join(",")
51
+ d = contents.map{|x| x.data_str}.join
52
+ run "#{cmd} #{r}#{c}\n#{d}"
53
+ nil
54
+ end
55
+ private :_plot_splot
56
+
57
+ # replot is not recommended, use refresh
58
+ def replot
59
+ run "replot\n#{@last_data}"
60
+ nil
61
+ end
62
+
63
+ # The `set` command is used to set _lots_ of options.
64
+ def set(*args)
65
+ _set_unset("set",args)
66
+ nil
67
+ end
68
+
69
+ # The `unset` command is used to return to their default state.
70
+ def unset(*args)
71
+ _set_unset("unset",args)
72
+ nil
73
+ end
74
+
75
+ def _set_unset(cmd,args)
76
+ args.each do |a|
77
+ case a
78
+ when Hash
79
+ a.each do |k,v|
80
+ run "#{cmd} #{KvItem.new(k,v)}"
81
+ end
82
+ else
83
+ run "#{cmd} #{a}"
84
+ end
85
+ end
86
+ nil
87
+ end
88
+ private :_set_unset
89
+
90
+ # The `help` command displays built-in help.
91
+ def help(s=nil)
92
+ puts send_cmd "help #{s}\n\n"
93
+ end
94
+
95
+ # The `show` command shows their settings.
96
+ def show(x)
97
+ puts send_cmd "show #{x}"
98
+ end
99
+
100
+ # The `reset` command causes all graph-related options that can be
101
+ # set with the `set` command to take on their default values.
102
+ def reset(x=nil)
103
+ run "reset #{x}"
104
+ nil
105
+ end
106
+
107
+ # The `pause` command used to wait for events on window.
108
+ # Carriage return entry (-1 is given for argument) and
109
+ # text display option is disabled.
110
+ # pause 10
111
+ # pause 'mouse'
112
+ # pause mouse:%w[keypress,button1,button2,button3,close,any]
113
+ def pause(*args)
114
+ send_cmd("pause #{OptsToS.new(*args)}").join.chomp
115
+ nil
116
+ end
117
+
118
+ # The `load` command executes each line of the specified input file.
119
+ def load(filename)
120
+ send_cmd "load '#{filename}'"
121
+ nil
122
+ end
123
+
124
+ alias kernel_raise :raise
125
+
126
+ # The `raise` command raises plot window(s)
127
+ def raise_plot(plot_window_nb=nil)
128
+ send_cmd "raise #{plot_window_nb}"
129
+ nil
130
+ end
131
+ alias raise :raise_plot
132
+
133
+ # The `lower` command lowers plot window(s)
134
+ def lower_plot(plot_window_nb=nil)
135
+ send_cmd "lower #{plot_window_nb}"
136
+ nil
137
+ end
138
+ alias lower :lower_plot
139
+
140
+ # The `clear` command erases the current screen or output device as specified
141
+ # by `set output`. This usually generates a formfeed on hardcopy devices.
142
+ def clear
143
+ send_cmd "clear"
144
+ nil
145
+ end
146
+
147
+ # The `exit` and `quit` commands will exit `gnuplot`.
148
+ def exit
149
+ send_cmd "exit"
150
+ nil
151
+ end
152
+
153
+ # The `exit` and `quit` commands will exit `gnuplot`.
154
+ def quit
155
+ send_cmd "quit"
156
+ nil
157
+ end
158
+
159
+ # The `refresh` reformats and redraws the current plot using the
160
+ # data already read in.
161
+ def refresh
162
+ send_cmd "reflesh"
163
+ nil
164
+ end
165
+
166
+ # `var` returns Gnuplot variable (not Gnuplot command)
167
+ def var(name)
168
+ res = send_cmd("print #{name}").join("").chomp
169
+ if /undefined variable:/ =~ res
170
+ kernel_raise GnuplotError,res.strip
171
+ end
172
+ res
173
+ end
174
+
175
+ # turn on debug
176
+ def debug_on
177
+ @debug = true
178
+ end
179
+
180
+ # turn off debug
181
+ def debug_off
182
+ @debug = false
183
+ end
184
+
185
+ #other_commands = %w[
186
+ # bind
187
+ # call
188
+ # cd
189
+ # do
190
+ # evaluate
191
+ # fit
192
+ # history
193
+ # if
194
+ # print
195
+ # pwd
196
+ # reread
197
+ # save
198
+ # shell
199
+ # stats
200
+ # system
201
+ # test
202
+ # update
203
+ # while
204
+ #]
205
+
206
+ # for irb workspace name
207
+ def to_s
208
+ "gnuplot"
209
+ end
210
+
211
+ def run(s)
212
+ res = send_cmd(s)
213
+ if !res.empty?
214
+ if res.size > 7
215
+ msg = "\n"+res[0..5].join("")+" :\n"
216
+ else
217
+ msg = "\n"+res.join("")
218
+ end
219
+ kernel_raise GnuplotError,msg
220
+ end
221
+ nil
222
+ end
223
+ private :run
224
+
225
+ def send_cmd(s)
226
+ puts "<"+s if @debug
227
+ @iow.puts s
228
+ @iow.flush
229
+ @iow.puts "print '_end_of_cmd_'"
230
+ @iow.flush
231
+ @history << s
232
+ res = []
233
+ while line=@ior.gets
234
+ puts ">"+line if @debug
235
+ break if /^_end_of_cmd_$/ =~ line
236
+ res << line
237
+ end
238
+ res # = res.chomp.strip
239
+ end
240
+ private :send_cmd
241
+
242
+ def parse_plot_args(args)
243
+ list = [[]]
244
+ item = PlotItem.new
245
+ list << item
246
+ args.each do |arg|
247
+ case arg
248
+ when Range
249
+ list.first << arg
250
+ when Array
251
+ if arg.all?{|e| e.kind_of?(Range)}
252
+ list.first.concat(arg)
253
+ elsif PlotItem.is_data(arg)
254
+ item << arg
255
+ else
256
+ if list.last.empty?
257
+ list.pop
258
+ end
259
+ item = PlotItem.new(*arg)
260
+ list << item
261
+ end
262
+ when Hash
263
+ item << arg
264
+ item = PlotItem.new
265
+ list << item
266
+ else
267
+ item << arg
268
+ end
269
+ end
270
+ if list.last.empty?
271
+ list.pop
272
+ end
273
+ return list
274
+ end
275
+ private :parse_plot_args
276
+
277
+
278
+ # @private
279
+ class OptsToS # :nodoc: all
280
+ def initialize(*opts)
281
+ @opts = opts
282
+ end
283
+
284
+ def to_s
285
+ opts_to_s(*@opts)
286
+ end
287
+
288
+ def opts_to_s(*opts)
289
+ #p opts
290
+ sep = ","
291
+ opts.map do |opt|
292
+ sep = " " if !opt.kind_of?(Numeric)
293
+ case opt
294
+ when Array
295
+ opt.map{|v| "#{opts_to_s(*v)}"}.join(sep)
296
+ when Hash
297
+ opt.map{|k,v| KvItem.new(k,v).to_s}.compact.join(" ")
298
+ when Range
299
+ "[#{opt.begin}:#{opt.end}]"
300
+ else
301
+ opt.to_s
302
+ end
303
+ end.join(sep)
304
+ end
305
+ end
306
+
307
+ # @private
308
+ class KvItem # :nodoc: all
309
+ NEED_QUOTE = %w[
310
+ background
311
+ cblabel
312
+ clabel
313
+ dashtype
314
+ dt
315
+ font
316
+ format
317
+ format_cb
318
+ format_x
319
+ format_x2
320
+ format_xy
321
+ format_y
322
+ format_y2
323
+ format_z
324
+ output
325
+ rgb
326
+ timefmt
327
+ title
328
+ x2label
329
+ xlabel
330
+ y2label
331
+ ylabel
332
+ zlabel
333
+ ].map{|x| x.to_sym}
334
+
335
+ def initialize(k,v)
336
+ @k = k
337
+ @v = v
338
+ end
339
+
340
+ def need_quote?(k)
341
+ NEED_QUOTE.any? do |q|
342
+ /^#{k}/ =~ q
343
+ end
344
+ end
345
+
346
+ def to_s
347
+ kv_to_s(@k,@v)
348
+ end
349
+
350
+ def kv_to_s(k,v)
351
+ if need_quote?(k)
352
+ case v
353
+ when String
354
+ "#{k} #{v.inspect}"
355
+ when Array
356
+ "#{k} #{v[0].inspect} #{OptsToS.new(*v[1..-1])}"
357
+ end
358
+ else
359
+ case v
360
+ when String
361
+ "#{k} #{v}"
362
+ when TrueClass
363
+ "#{k}"
364
+ when NilClass
365
+ nil
366
+ when FalseClass
367
+ nil
368
+ when Array
369
+ "#{k} #{OptsToS.new(*v)}"
370
+ else
371
+ "#{k} #{OptsToS.new(v)}"
372
+ end
373
+ end
374
+ end
375
+ end # KvItem
376
+
377
+
378
+ # @private
379
+ class PlotItem # :nodoc: all
380
+
381
+ def self.is_data(a)
382
+ if a.kind_of? Array
383
+ if a.last.kind_of?(Hash)
384
+ return false
385
+ else
386
+ t = a.first.class
387
+ t = Numeric if t < Numeric
388
+ return a.all?{|e| e.kind_of?(t)}
389
+ end
390
+ elsif defined?(Numo::NArray)
391
+ return true if a.kind_of?(Numo::NArray)
392
+ elsif defined?(NArray)
393
+ return true if a.kind_of?(NArray)
394
+ elsif defined?(NMatrix)
395
+ return true if a.kind_of?(NMatix)
396
+ end
397
+ false
398
+ end
399
+
400
+ def initialize(*items)
401
+ @items = items
402
+ end
403
+
404
+ def <<(item)
405
+ @items << item
406
+ end
407
+
408
+ def empty?
409
+ @items.empty?
410
+ end
411
+
412
+ def parse_items
413
+ if !@options
414
+ if @items.empty?
415
+ return
416
+ elsif @items.first.kind_of? String
417
+ @function = @items.first
418
+ @options = @items[1..-1]
419
+ else
420
+ @data = []
421
+ @options = []
422
+ @items.each do |x|
423
+ if PlotItem.is_data(x)
424
+ @data << x
425
+ else
426
+ @options << x
427
+ end
428
+ end
429
+ if @data.size==1
430
+ a = @data[0]
431
+ if a.respond_to?(:shape)
432
+ if a.shape.size == 2
433
+ @matrix = true
434
+ end
435
+ end
436
+ end
437
+ end
438
+ end
439
+ end
440
+
441
+ def cmd_str
442
+ parse_items
443
+ if @function
444
+ "%s %s" % [@function, OptsToS.new(*@options)]
445
+ else
446
+ if @matrix
447
+ "'-' matrix %s" % OptsToS.new(*@options)
448
+ else
449
+ "'-' %s" % OptsToS.new(*@options)
450
+ end
451
+ end
452
+ end
453
+
454
+ def data_str
455
+ parse_items
456
+ if @function
457
+ nil
458
+ else
459
+ if @matrix
460
+ data2d_to_s(@data[0])+"\ne\n"
461
+ else
462
+ data1d_to_s(@data)+"e\n"
463
+ end
464
+ end
465
+ end
466
+
467
+ def data_format
468
+ @data_format || DATA_FORMAT
469
+ end
470
+
471
+ def data_format=(s)
472
+ @data_format = s
473
+ end
474
+
475
+ def data1d_to_s(a)
476
+ n = a.map{|e| e.size}.min
477
+ f = ([data_format]*a.size).join(" ")+"\n"
478
+ s = ""
479
+ n.times{|i| s << f % a.map{|e| e[i]}}
480
+ s
481
+ end
482
+
483
+ def data2d_to_s(a)
484
+ f = data_format
485
+ s = ""
486
+ a.to_a.each do |b|
487
+ s << b.map{|e| f%e}.join(" ")+"\n"
488
+ end
489
+ s
490
+ end
491
+ end # PlotItem
492
+ end # Numo::Gnuplot
493
+ end