carray 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (231) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +56 -0
  3. data/GPL +340 -0
  4. data/Gemfile +9 -0
  5. data/Gemfile.lock +33 -0
  6. data/LEGAL +50 -0
  7. data/NOTE +73 -0
  8. data/Rakefile +20 -0
  9. data/TODO +5 -0
  10. data/ca_iter_block.c +242 -0
  11. data/ca_iter_dimension.c +287 -0
  12. data/ca_iter_window.c +202 -0
  13. data/ca_obj_array.c +1189 -0
  14. data/ca_obj_bitarray.c +523 -0
  15. data/ca_obj_bitfield.c +636 -0
  16. data/ca_obj_block.c +885 -0
  17. data/ca_obj_fake.c +405 -0
  18. data/ca_obj_farray.c +482 -0
  19. data/ca_obj_field.c +625 -0
  20. data/ca_obj_grid.c +738 -0
  21. data/ca_obj_mapping.c +614 -0
  22. data/ca_obj_object.c +777 -0
  23. data/ca_obj_reduce.c +299 -0
  24. data/ca_obj_refer.c +627 -0
  25. data/ca_obj_repeat.c +640 -0
  26. data/ca_obj_select.c +558 -0
  27. data/ca_obj_shift.c +952 -0
  28. data/ca_obj_transpose.c +582 -0
  29. data/ca_obj_unbound_repeat.c +557 -0
  30. data/ca_obj_window.c +1023 -0
  31. data/carray.h +1381 -0
  32. data/carray_access.c +1798 -0
  33. data/carray_attribute.c +903 -0
  34. data/carray_call_cfunc.c +1107 -0
  35. data/carray_cast.c +1155 -0
  36. data/carray_cast_func.rb +498 -0
  37. data/carray_class.c +132 -0
  38. data/carray_conversion.c +518 -0
  39. data/carray_copy.c +453 -0
  40. data/carray_core.c +1307 -0
  41. data/carray_element.c +572 -0
  42. data/carray_generate.c +681 -0
  43. data/carray_iterator.c +630 -0
  44. data/carray_loop.c +462 -0
  45. data/carray_mask.c +1174 -0
  46. data/carray_math.rb +834 -0
  47. data/carray_numeric.c +257 -0
  48. data/carray_operator.c +582 -0
  49. data/carray_order.c +1040 -0
  50. data/carray_random.c +529 -0
  51. data/carray_sort_addr.c +261 -0
  52. data/carray_stat.c +2102 -0
  53. data/carray_stat_proc.rb +1990 -0
  54. data/carray_test.c +602 -0
  55. data/carray_undef.c +69 -0
  56. data/carray_utils.c +740 -0
  57. data/ext/calculus/carray_calculus.c +792 -0
  58. data/ext/calculus/carray_interp.c +355 -0
  59. data/ext/calculus/extconf.rb +12 -0
  60. data/ext/calculus/lib/autoload/autoload_math_calculus.rb +2 -0
  61. data/ext/calculus/lib/math/calculus.rb +119 -0
  62. data/ext/calculus/lib/math/interp/adapter_interp1d.rb +31 -0
  63. data/ext/dataframe/API.txt +11 -0
  64. data/ext/dataframe/extconf.rb +3 -0
  65. data/ext/dataframe/lib/carray/autoload/autoload_dataframe_dataframe.rb +14 -0
  66. data/ext/dataframe/lib/carray/dataframe/dataframe.rb +1104 -0
  67. data/ext/dataframe/sample/test_uniq_sort.rb +5 -0
  68. data/ext/fortio/extconf.rb +3 -0
  69. data/ext/fortio/lib/carray/autoload/autoload_fortran_format.rb +5 -0
  70. data/ext/fortio/lib/carray/io/fortran_format.rb +43 -0
  71. data/ext/fortio/lib/fortio.rb +3 -0
  72. data/ext/fortio/lib/fortio/fortran_format.rb +603 -0
  73. data/ext/fortio/lib/fortio/fortran_format.tab.rb +536 -0
  74. data/ext/fortio/lib/fortio/fortran_format.y +215 -0
  75. data/ext/fortio/lib/fortio/fortran_namelist.rb +151 -0
  76. data/ext/fortio/lib/fortio/fortran_namelist.tab.rb +470 -0
  77. data/ext/fortio/lib/fortio/fortran_namelist.y +213 -0
  78. data/ext/fortio/lib/fortio/fortran_sequential.rb +345 -0
  79. data/ext/fortio/ruby_fortio.c +182 -0
  80. data/ext/fortio/test/test_H.rb +5 -0
  81. data/ext/fortio/test/test_T.rb +7 -0
  82. data/ext/fortio/test/test_fortran_format.rb +86 -0
  83. data/ext/fortio/test/test_namelist.rb +25 -0
  84. data/ext/fortio/test/test_sequential.rb +13 -0
  85. data/ext/fortio/test/test_sequential2.rb +13 -0
  86. data/ext/fortio/work/test.rb +10 -0
  87. data/ext/fortio/work/test_e.rb +19 -0
  88. data/ext/fortio/work/test_ep.rb +10 -0
  89. data/ext/fortio/work/test_parse.rb +12 -0
  90. data/ext/imagemap/carray_imagemap.c +495 -0
  91. data/ext/imagemap/doc/call_graph.dot +28 -0
  92. data/ext/imagemap/draw.c +567 -0
  93. data/ext/imagemap/extconf.rb +13 -0
  94. data/ext/imagemap/lib/autoload/autoload_graphics_imagemap.rb +1 -0
  95. data/ext/imagemap/lib/graphics/imagemap.rb +273 -0
  96. data/ext/imagemap/lib/image_map.rb +4 -0
  97. data/ext/imagemap/test/swath_index.rb +83 -0
  98. data/ext/imagemap/test/swath_warp.rb +99 -0
  99. data/ext/imagemap/test/test.rb +23 -0
  100. data/ext/imagemap/test/test_image.rb +42 -0
  101. data/ext/imagemap/test/test_line.rb +14 -0
  102. data/ext/imagemap/test/test_rotate.rb +17 -0
  103. data/ext/imagemap/test/test_triangle.rb +20 -0
  104. data/ext/imagemap/test/test_warp.rb +26 -0
  105. data/ext/mathfunc/carray_mathfunc.c +321 -0
  106. data/ext/mathfunc/extconf.rb +18 -0
  107. data/ext/mathfunc/lib/autoload/autoload_math_mathfunc.rb +1 -0
  108. data/ext/mathfunc/lib/math/mathfunc.rb +15 -0
  109. data/ext/mathfunc/test/test_hypot.rb +5 -0
  110. data/ext/mathfunc/test/test_j0.rb +22 -0
  111. data/ext/mathfunc/test/test_jn.rb +8 -0
  112. data/ext/mathfunc/test/test_sph.rb +9 -0
  113. data/ext/narray/README +22 -0
  114. data/ext/narray/ca_wrap_narray.c +491 -0
  115. data/ext/narray/carray_narray.c +21 -0
  116. data/ext/narray/extconf.rb +57 -0
  117. data/ext/narray/lib/autoload/autoload_math_narray.rb +1 -0
  118. data/ext/narray/lib/autoload/autoload_math_narray_miss.rb +11 -0
  119. data/ext/narray/lib/math/narray.rb +17 -0
  120. data/ext/narray/lib/math/narray_miss.rb +45 -0
  121. data/extconf.rb +3 -25
  122. data/lib/carray.rb +28 -0
  123. data/lib/carray/autoload/autoload_base.rb +23 -0
  124. data/lib/carray/autoload/autoload_graphics_gnuplot.rb +2 -0
  125. data/lib/carray/autoload/autoload_io_csv.rb +14 -0
  126. data/lib/carray/autoload/autoload_io_excel.rb +5 -0
  127. data/lib/carray/autoload/autoload_io_imagemagick.rb +6 -0
  128. data/lib/carray/autoload/autoload_io_pg.rb +6 -0
  129. data/lib/carray/autoload/autoload_io_sqlite3.rb +12 -0
  130. data/lib/carray/autoload/autoload_io_table.rb +1 -0
  131. data/lib/carray/autoload/autoload_math_histogram.rb +5 -0
  132. data/lib/carray/autoload/autoload_math_interp.rb +4 -0
  133. data/lib/carray/autoload/autoload_math_recurrence.rb +6 -0
  134. data/lib/carray/autoload/autoload_object_iterator.rb +1 -0
  135. data/lib/carray/autoload/autoload_object_link.rb +1 -0
  136. data/lib/carray/autoload/autoload_object_pack.rb +2 -0
  137. data/lib/carray/base/autoload.rb +94 -0
  138. data/lib/carray/base/basic.rb +1051 -0
  139. data/lib/carray/base/inspect.rb +252 -0
  140. data/lib/carray/base/iterator.rb +367 -0
  141. data/lib/carray/base/math.rb +403 -0
  142. data/lib/carray/base/obsolete.rb +93 -0
  143. data/lib/carray/base/serialize.rb +260 -0
  144. data/lib/carray/base/struct.rb +634 -0
  145. data/lib/carray/graphics/gnuplot.rb +2116 -0
  146. data/lib/carray/info.rb +112 -0
  147. data/lib/carray/io/csv.rb +560 -0
  148. data/lib/carray/io/excel.rb +26 -0
  149. data/lib/carray/io/imagemagick.rb +231 -0
  150. data/lib/carray/io/pg.rb +101 -0
  151. data/lib/carray/io/sqlite3.rb +202 -0
  152. data/lib/carray/io/table.rb +77 -0
  153. data/lib/carray/math/histogram.rb +179 -0
  154. data/lib/carray/math/interp.rb +57 -0
  155. data/lib/carray/math/interp/adapter_gsl_spline.rb +47 -0
  156. data/lib/carray/math/recurrence.rb +95 -0
  157. data/lib/carray/mkmf.rb +145 -0
  158. data/lib/carray/object/ca_obj_iterator.rb +52 -0
  159. data/lib/carray/object/ca_obj_link.rb +52 -0
  160. data/lib/carray/object/ca_obj_pack.rb +101 -0
  161. data/mkmath.rb +731 -0
  162. data/mt19937ar.c +182 -0
  163. data/mt19937ar.h +86 -0
  164. data/rdoc_main.rb +27 -0
  165. data/rdoc_math.rb +5 -0
  166. data/rdoc_stat.rb +31 -0
  167. data/ruby_carray.c +242 -0
  168. data/ruby_ccomplex.c +497 -0
  169. data/ruby_float_func.c +83 -0
  170. data/spec/CABlockIterator/CABlockIterator_spec.rb +113 -0
  171. data/spec/CArray/bug/store_spec.rb +27 -0
  172. data/spec/CArray/index/repeat_spec.rb +10 -0
  173. data/spec/CArray/method/eq_spec.rb +80 -0
  174. data/spec/CArray/method/is_nan_spec.rb +12 -0
  175. data/spec/CArray/method/ne_spec.rb +18 -0
  176. data/spec/CArray/method/round_spec.rb +11 -0
  177. data/spec/CArray/object/_attribute_spec.rb +32 -0
  178. data/spec/CArray/object/s_new_spec.rb +31 -0
  179. data/spec/CArray/serialize/Serialization_spec.rb +89 -0
  180. data/spec/spec_all.rb +11 -0
  181. data/test/test_ALL.rb +50 -0
  182. data/test/test_CABitfield.rb +59 -0
  183. data/test/test_CABlock.rb +208 -0
  184. data/test/test_CAField.rb +40 -0
  185. data/test/test_CAGrid.rb +76 -0
  186. data/test/test_CAMapping.rb +106 -0
  187. data/test/test_CAMmap.rb +11 -0
  188. data/test/test_CARefer.rb +94 -0
  189. data/test/test_CARepeat.rb +66 -0
  190. data/test/test_CASelect.rb +23 -0
  191. data/test/test_CAShift.rb +17 -0
  192. data/test/test_CATranspose.rb +61 -0
  193. data/test/test_CAVirtual.rb +214 -0
  194. data/test/test_CAWindow.rb +55 -0
  195. data/test/test_CAWrap.rb +9 -0
  196. data/test/test_CArray.rb +228 -0
  197. data/test/test_CComplex.rb +83 -0
  198. data/test/test_CScalar.rb +91 -0
  199. data/test/test_attribute.rb +281 -0
  200. data/test/test_block_iterator.rb +17 -0
  201. data/test/test_boolean.rb +99 -0
  202. data/test/test_cast.rb +33 -0
  203. data/test/test_class.rb +85 -0
  204. data/test/test_complex.rb +43 -0
  205. data/test/test_composite.rb +125 -0
  206. data/test/test_convert.rb +79 -0
  207. data/test/test_copy.rb +141 -0
  208. data/test/test_creation.rb +85 -0
  209. data/test/test_element.rb +146 -0
  210. data/test/test_extream.rb +55 -0
  211. data/test/test_generate.rb +75 -0
  212. data/test/test_index.rb +71 -0
  213. data/test/test_mask.rb +578 -0
  214. data/test/test_math.rb +98 -0
  215. data/test/test_narray.rb +64 -0
  216. data/test/test_order.rb +147 -0
  217. data/test/test_random.rb +15 -0
  218. data/test/test_ref_store.rb +211 -0
  219. data/test/test_stat.rb +414 -0
  220. data/test/test_struct.rb +72 -0
  221. data/test/test_virtual.rb +49 -0
  222. data/utils/ca_ase.rb +21 -0
  223. data/utils/ca_methods.rb +15 -0
  224. data/utils/cast_checker.rb +30 -0
  225. data/utils/create_rdoc.sh +9 -0
  226. data/utils/diff_method.rb +52 -0
  227. data/utils/extract_rdoc.rb +27 -0
  228. data/utils/make_tgz.sh +3 -0
  229. data/utils/remove_resource_fork.sh +5 -0
  230. data/version.h +3 -3
  231. metadata +266 -1
@@ -0,0 +1,2116 @@
1
+ # ----------------------------------------------------------------------------
2
+ #
3
+ # carray/graphics/gnuplot.rb
4
+ #
5
+ # This file is part of Ruby/CArray extension library.
6
+ # You can redistribute it and/or modify it under the terms of
7
+ # the Ruby Licence.
8
+ #
9
+ # Copyright (C) 2005 Hiroki Motoyoshi
10
+ #
11
+ # ----------------------------------------------------------------------------
12
+
13
+ require "date"
14
+ require "time"
15
+ require "open3"
16
+ require "carray"
17
+ require "ostruct"
18
+
19
+ def CA.gnuplot (*argv, &block)
20
+ CA::Gnuplot.new(*argv, &block)
21
+ end
22
+
23
+ class CA::Gnuplot # :nodoc:
24
+
25
+ if File.directory?("/tmp")
26
+ TMPDIR = "/tmp"
27
+ else
28
+ TMPDIR = "."
29
+ end
30
+
31
+ def initialize (command = "gnuplot", stdout: STDOUT, &block)
32
+ begin
33
+ @io, @stdout, @stderr = Open3.popen3(command + " -noraise")
34
+ rescue NotImplementedError
35
+ raise NotImplementedError, "system dosen't support Open3.popen3"
36
+ end
37
+
38
+ @defaults = {}
39
+ @temp_file_count = 0
40
+ @multiplot_mode = false
41
+ @script_mode = false
42
+ @pause_mode = :default
43
+ @reset_mode = :default
44
+ @init = nil
45
+ @last = nil
46
+ @listen = Thread.start {
47
+ Thread.abort_on_exception = true
48
+ begin
49
+ stdout << @stdout.gets
50
+ while line = @stdout.gets ### read(1024)
51
+ # unless line =~ /\Agnuplot>/
52
+ stdout << line
53
+ stdout.flush
54
+ # end
55
+ end
56
+ rescue IOError ### @stdout may externally closed
57
+ end
58
+ }
59
+
60
+ @gnuplot_version = evaluate("GPVAL_VERSION").to_f
61
+
62
+ epoch = evaluate %{strftime("%Y-%m-%d",0)}
63
+ @EP_T = Time.parse(epoch)
64
+ @EP_D = Date.parse(epoch)
65
+ @EP_DT = DateTime.parse(epoch)
66
+
67
+ @reset_script = reset_script() ## RESET_SCRIPT
68
+
69
+ reset
70
+ if block_given?
71
+ begin
72
+ case block.arity
73
+ when 1
74
+ yield(self)
75
+ when -1, 0
76
+ instance_exec(&block)
77
+ else
78
+ raise "invalid # of block parameters"
79
+ end
80
+ ensure
81
+ self.close
82
+ end
83
+ end
84
+ end
85
+
86
+ attr_accessor :debug, :script_mode
87
+ attr_reader :multiplot_mode, :multiplot_option, :last
88
+
89
+ def close
90
+ put("quit")
91
+ @io.close
92
+ @listen.join
93
+ @stdout.close
94
+ @stderr.close
95
+ end
96
+
97
+ def put (*args)
98
+ lines = args.map {|s| s.respond_to?(:to_gnuplot) ? s.to_gnuplot : s.to_s }
99
+ command = lines.join("\n")
100
+ if @debug
101
+ STDERR.puts command
102
+ end
103
+ thread = Thread.start {
104
+ begin
105
+ size = command.size
106
+ s = 0
107
+ while s < size
108
+ s += @io.write(command[s, 2048])
109
+ end
110
+ @io.puts
111
+ @io.puts %{ print "SIGNAL FOR CA::Gnuplot" }
112
+ @io.flush
113
+ rescue Errno::EPIPE
114
+ end
115
+ }
116
+ output = ""
117
+ while line = @stderr.gets
118
+ case line.chomp
119
+ when /SIGNAL FOR CA::Gnuplot$/
120
+ STDERR.print(output) if @debug and not output.empty?
121
+ return output.chomp
122
+ when / line \d+: (.*?) /
123
+ if $1 =~ /warning:/
124
+ output << line
125
+ STDERR.print output
126
+ next
127
+ else
128
+ output << line
129
+ STDERR.print output
130
+ raise "Gnuplot Processor Error"
131
+ end
132
+ else
133
+ output << line
134
+ end
135
+ end
136
+ ensure
137
+ thread.join
138
+ end
139
+
140
+ def reset_script
141
+ # TO BE COMENNTED OUT
142
+ # set size ratio 0 1,1
143
+ # set origin 0,0
144
+ # set lmargin -1
145
+ # set bmargin -1
146
+ # set rmargin -1
147
+ # set tmargin -1
148
+ # set locale "ja_JP.UTF-8"
149
+ # set decimalsign
150
+ # set encoding
151
+ # set loadpath
152
+ # set fontpath
153
+ # set psdir
154
+ # set fit brief errorvariables nocovariancevariables errorscaling prescale nowrap
155
+ script = put(%{ save set "|cat 1>&2" }).split($/)
156
+ script.delete_if {|s| s =~ /^set size ratio/ }
157
+ script.delete_if {|s| s =~ /^set origin/ }
158
+ script.delete_if {|s| s =~ /^set .margin/ }
159
+ script.delete_if {|s| s =~ /^set locale/ }
160
+ script.delete_if {|s| s =~ /^set decimalsign/ }
161
+ script.delete_if {|s| s =~ /^set encoding/ }
162
+ script.delete_if {|s| s =~ /^set loadpath/ }
163
+ script.delete_if {|s| s =~ /^set fontpath/ }
164
+ script.delete_if {|s| s =~ /^set psdir/ }
165
+ script.delete_if {|s| s =~ /^set fit/ }
166
+ return script.join($/)
167
+ end
168
+
169
+ def debug_on
170
+ self.debug = true
171
+ end
172
+
173
+ def debug_off
174
+ self.debug = false
175
+ end
176
+
177
+ def init (&block)
178
+ @init = block
179
+ @init.call
180
+ return @init
181
+ end
182
+
183
+ def set (*argv)
184
+ put "set " + argv.map{|s| s.gsub(/\n/,'') }.join(" ")
185
+ end
186
+
187
+ def unset (*argv)
188
+ put "unset " + argv.map{|s| s.gsub(/\n/,'') }.join(" ")
189
+ end
190
+
191
+ def evaluate (expr)
192
+ return put("print #{expr}")
193
+ end
194
+
195
+ def color_style (fgcolor, bgcolor = nil, framecolor = nil, shadowcolor = nil)
196
+ if fgcolor
197
+ @defaults[:fgcolor] = fgcolor
198
+ put %{ fgcolor = "#{fgcolor}" }
199
+ end
200
+ if bgcolor
201
+ @defaults[:bgcolor] = bgcolor
202
+ put %{ bgcolor = "#{bgcolor}" }
203
+ end
204
+ if framecolor
205
+ @defaults[:framecolor] = framecolor
206
+ put %{ framecolor = "#{framecolor}" }
207
+ end
208
+ if shadowcolor
209
+ @defaults[:shadowcolor] = shadowcolor
210
+ put %{ shadowcolor = "#{shadowcolor}" }
211
+ end
212
+ end
213
+
214
+ def framecolor (spec)
215
+ @defaults[:framecolor] = spec
216
+ put %{ framecolor = "#{spec}" }
217
+ end
218
+
219
+ alias frame_color framecolor
220
+
221
+ def shadowcolor (spec)
222
+ @defaults[:shadowcolor] = spec
223
+ put %{ shadowcolor = "#{spec}" }
224
+ end
225
+
226
+ alias shadow_color shadowcolor
227
+
228
+ def bgcolor (spec)
229
+ @defaults[:bgcolor] = spec
230
+ put %{ bgcolor = "#{spec}" }
231
+ end
232
+
233
+ alias bg_color bgcolor
234
+
235
+ def fgcolor (spec)
236
+ @defaults[:fgcolor] = spec
237
+ put %{ fgcolor = "#{spec}" }
238
+ end
239
+
240
+ alias fg_color fgcolor
241
+
242
+ def color_scheme (*names)
243
+ if @gnuplot_version >= 5.0
244
+ case names.first
245
+ when :keynote
246
+ put %{
247
+ set linetype 1 lc rgb "#BB2C2F"
248
+ set linetype 2 lc rgb "#5E9648"
249
+ set linetype 3 lc rgb "#2E578B"
250
+ set linetype 4 lc rgb "#6F3B77"
251
+ set linetype 5 lc rgb "#002C63"
252
+ set linetype 6 lc rgb "#E6A03D"
253
+ set linetype 7 lc rgb "#7D807E"
254
+ set linetype 8 lc rgb "#1B0C00"
255
+ set linetype cycle 8
256
+ }
257
+ when :grads
258
+ put %{
259
+ set linetype 2 lc rgb "#fa3c3c"
260
+ set linetype 3 lc rgb "#00dc00"
261
+ set linetype 4 lc rgb "#1e3cff"
262
+ set linetype 5 lc rgb "#00c8c8"
263
+ set linetype 6 lc rgb "#f00082"
264
+ set linetype 7 lc rgb "#e6dc32"
265
+ set linetype 8 lc rgb "#f08228"
266
+ set linetype 9 lc rgb "#a000c8"
267
+ set linetype 10 lc rgb "#a0e632"
268
+ set linetype 11 lc rgb "#00a0ff"
269
+ set linetype 12 lc rgb "#e6af2d"
270
+ set linetype 13 lc rgb "#00d28c"
271
+ set linetype 14 lc rgb "#8200dc"
272
+ set linetype 15 lc rgb "#aaaaaa"
273
+ set linetype cycle 15
274
+ }
275
+ when :podo
276
+ set %{ colorsequence podo }
277
+ when :classic
278
+ set %{ colorsequence classic }
279
+ when :default
280
+ set %{ colorsequence default }
281
+ else
282
+ style = []
283
+ names.each_with_index do |col, i|
284
+ style << %{ set linetype #{i+1} lc rgb "#{col.to_s}"}
285
+ end
286
+ put style.join("\n")
287
+ end
288
+ else
289
+ case names.first
290
+ when :keynote
291
+ put %{
292
+ set style increment user
293
+ set style line 1 lc rgb "#BB2C2F"
294
+ set style line 2 lc rgb "#5E9648"
295
+ set style line 3 lc rgb "#2E578B"
296
+ set style line 4 lc rgb "#6F3B77"
297
+ set style line 5 lc rgb "#002C63"
298
+ set style line 6 lc rgb "#E6A03D"
299
+ set style line 7 lc rgb "#7D807E"
300
+ set style line 8 lc rgb "#1B0C00"
301
+ }
302
+ when :grads
303
+ put %{
304
+ set style increment user
305
+ set style line 2 lc rgb "#fa3c3c"
306
+ set style line 3 lc rgb "#00dc00"
307
+ set style line 4 lc rgb "#1e3cff"
308
+ set style line 5 lc rgb "#00c8c8"
309
+ set style line 6 lc rgb "#f00082"
310
+ set style line 7 lc rgb "#e6dc32"
311
+ set style line 8 lc rgb "#f08228"
312
+ set style line 9 lc rgb "#a000c8"
313
+ set style line 10 lc rgb "#a0e632"
314
+ set style line 11 lc rgb "#00a0ff"
315
+ set style line 12 lc rgb "#e6af2d"
316
+ set style line 13 lc rgb "#00d28c"
317
+ set style line 14 lc rgb "#8200dc"
318
+ set style line 15 lc rgb "#aaaaaa"
319
+ }
320
+ else
321
+ style = ["set style increment user"]
322
+ names.each_with_index do |col, i|
323
+ style << %{ set style line #{i+1} lc rgb "#{col.to_s}"}
324
+ end
325
+ put style.join("\n")
326
+ end
327
+ end
328
+ end
329
+
330
+
331
+ def pause_mode (arg = nil)
332
+ # :none - no pausing
333
+ # :default - return on terminal
334
+ # :mouse - mouse click on window
335
+ # :keypress - keypress on window
336
+ orig = @pause_mode
337
+ if arg
338
+ @pause_mode = arg
339
+ else
340
+ @pause_mode = :default
341
+ end
342
+ if block_given?
343
+ begin
344
+ yield
345
+ ensure
346
+ @pause_mode = orig
347
+ end
348
+ end
349
+ end
350
+
351
+ def pause (arg = -1)
352
+ if @multiplot_mode
353
+ return
354
+ else
355
+ case @pause_mode
356
+ when :none
357
+ return
358
+ when :mouse
359
+ pause_mouse
360
+ when :keypress
361
+ pause_keypress
362
+ else # :key
363
+ term = evaluate("GPVAL_TERM")
364
+ case term
365
+ when /x11/, /aqua/, /wxt/
366
+ STDIN.gets
367
+ end
368
+ end
369
+ end
370
+ end
371
+
372
+ def pause_mouse
373
+ put "pause mouse"
374
+ mx = evaluate "MOUSE_X"
375
+ my = evaluate "MOUSE_Y"
376
+ mk = evaluate "MOUSE_KEY"
377
+ return [mx, my, mk]
378
+ end
379
+
380
+ def pause_keypress
381
+ put "pause mouse keypress"
382
+ mx = evaluate "MOUSE_X"
383
+ my = evaluate "MOUSE_Y"
384
+ mk = evaluate "MOUSE_KEY"
385
+ return [mx, my, mk]
386
+ end
387
+
388
+ def reset_mode (arg = nil)
389
+ orig = @reset_mode
390
+ if arg
391
+ @reset_mode = arg
392
+ else
393
+ @reset_mode = :default
394
+ end
395
+ if block_given?
396
+ begin
397
+ yield
398
+ ensure
399
+ @reset_mode = orig
400
+ end
401
+ end
402
+ end
403
+
404
+ def reset ()
405
+ if @script_mode or @reset_mode == :none
406
+ return
407
+ end
408
+ if @multiplot_mode and
409
+ ( @multiplot_option[:layout] or @multiplot_option[:noreset] )
410
+ put @reset_script
411
+ put("set xyplane relative 0",
412
+ "set key Left reverse noautotitle")
413
+ else
414
+ put "reset"
415
+ put("set xyplane relative 0",
416
+ "set key Left reverse noautotitle")
417
+ end
418
+ end
419
+
420
+ def terminal (text)
421
+ text = text.split("\n").map{|l| l.strip }.join(" ").strip
422
+ put("set term #{text}")
423
+ end
424
+
425
+ def output (text)
426
+ @output = text
427
+ text = text.split("\n").map{|l| l.strip }.join(" ").strip
428
+ put("set output '#{text}'")
429
+ end
430
+
431
+ def time (data)
432
+ case data
433
+ when Numeric
434
+ data
435
+ when String
436
+ Time.parse(data) - @EP_T
437
+ when Time
438
+ data - @EP_T
439
+ when Date
440
+ (data - @EP_D)*86400
441
+ when DateTime
442
+ (data - @EP_DT)*86400
443
+ when CArray
444
+ return data.convert(CA_DOUBLE){|x|
445
+ case x
446
+ when Numeric
447
+ x
448
+ when Time
449
+ x - @EP_T
450
+ when Date
451
+ (x - @EP_D)*86400
452
+ when DateTime
453
+ (x - @EP_DT)*86400
454
+ when String
455
+ Time.parse(x) - @EP_T
456
+ end
457
+ }
458
+ when Range
459
+ time(data.first)..time(data.last)
460
+ end
461
+ end
462
+
463
+ def csv (*args)
464
+ list = []
465
+ args.each do |arg|
466
+ case arg
467
+ when Array
468
+ list.push(arg.to_ca)
469
+ else
470
+ list.push(arg)
471
+ end
472
+ end
473
+ return CArray.join(:object, list).to_csv
474
+ end
475
+
476
+ private
477
+
478
+ def with_tempfile (nfiles=1)
479
+ tempfile = Array.new(nfiles) {
480
+ @temp_file_count += 1
481
+ File.join(TMPDIR, "CA_Gnuplot_#{$$}_#{@temp_file_count}.dat")
482
+ }
483
+ yield(*tempfile)
484
+ ensure
485
+ tempfile.each do |file|
486
+ if File.exist?(file)
487
+ File.unlink(file)
488
+ end
489
+ end
490
+ end
491
+
492
+ def parse_args (argv, &block)
493
+ opt = @defaults.clone
494
+ if argv.size >= 1 and argv.last.is_a?(Hash)
495
+ opt.update(argv.pop)
496
+ elsif argv.size >= 1 and argv.last.is_a?(Option)
497
+ opt = argv.pop
498
+ end
499
+ if block
500
+ block.call(argv)
501
+ end
502
+ plots = argv.clone
503
+ if opt.is_a? Option
504
+ return plots, opt
505
+ else
506
+ return plots, Option.new(self, opt)
507
+ end
508
+ end
509
+
510
+ def parse_data (list)
511
+ list = list.clone
512
+ conf = []
513
+ while not list.empty? and
514
+ ( list.last.is_a?(Fixnum) or
515
+ list.last.is_a?(Symbol) or
516
+ list.last.is_a?(String) or
517
+ list.last.nil? )
518
+ conf.unshift(list.pop)
519
+ end
520
+ if conf.last.is_a?(Fixnum)
521
+ idx = conf.pop
522
+ case idx
523
+ when 1,2
524
+ iy = idx
525
+ axis = "x1y#{iy}"
526
+ when 11,12,21,22
527
+ ix = idx / 10
528
+ iy = idx % 10
529
+ axis = "x#{ix}y#{iy}"
530
+ else
531
+ raise "unknown axis specification"
532
+ end
533
+ end
534
+ if conf.last.is_a?(Symbol)
535
+ axis = conf.pop.to_s
536
+ end
537
+ using_ok = false
538
+ using = nil
539
+ if (conf.size == 2 or conf.size == 3 or conf.size == 4)
540
+ if conf.first =~ /^every /
541
+ dataspec = conf.shift
542
+ elsif conf.first =~ /^using /
543
+ using = conf.shift
544
+ using_ok = true
545
+ else
546
+ dataspec = nil
547
+ end
548
+ else
549
+ dataspec = nil
550
+ end
551
+ title, with = *conf
552
+ if title =~ /\A\s*(col|column|columnhead|columnheader(\(.*?\)|))\s*\z/
553
+ title = $1
554
+ else
555
+ title = %{"#{title}"}
556
+ end
557
+ return list, dataspec, using, title, with, axis
558
+ end
559
+
560
+ def histogram_tics (names)
561
+ return names.to_a.map.with_index {|n,i| [i,n.to_s]}
562
+ end
563
+
564
+ public
565
+
566
+ def plot_number
567
+ return @multiplot_plot_number
568
+ end
569
+
570
+ def multiplot (option = {})
571
+ @multiplot_mode = true
572
+ @multiplot_option = option
573
+ @multiplot_plot_number = 1
574
+ @saved_init = @init
575
+ options = ""
576
+ if option[:layout]
577
+ options << " layout " + option[:layout].join(",")
578
+ if option[:columnsfirst]
579
+ options << " columnsfirst "
580
+ else
581
+ options << " rowsfirst "
582
+ end
583
+ if option[:upwards]
584
+ options << " upwards "
585
+ else
586
+ options << " downwards "
587
+ end
588
+ end
589
+ if option[:scale]
590
+ options << " scale " + option[:scale].join(",")
591
+ end
592
+ if option[:offset]
593
+ options << " offset " + option[:offset].join(",")
594
+ end
595
+ if option[:title]
596
+ options << " title '" + option[:title] + "'"
597
+ end
598
+ put( "set multiplot" + options )
599
+ reset()
600
+ yield
601
+ ensure
602
+ put( "unset multiplot" )
603
+ @multiplot_option = nil
604
+ @multiplot_mode = false
605
+ @multiplot_plot_number = 0
606
+ @init = @saved_init
607
+ unless option[:nopause]
608
+ pause
609
+ end
610
+ unless option[:noreset]
611
+ reset
612
+ end
613
+ end
614
+
615
+ def canvas (*argv, &block)
616
+ plots, opt = parse_args(argv, &block)
617
+ put %{
618
+ unset xtics
619
+ unset x2tics
620
+ unset ytics
621
+ unset y2tics
622
+ unset xlabel
623
+ unset ylabel
624
+ unset x2label
625
+ unset y2label
626
+ unset key
627
+ }
628
+ opt.set(:margin, :title, :bgcolor,
629
+ :xaxis, :yaxis, :x2axis, :y2axis,
630
+ :border, :parametric,
631
+ :options)
632
+ put %{
633
+ plot "-" with dots
634
+ -1e30,-1e30
635
+ e
636
+ }
637
+ if @multiplot_mode
638
+ @multiplot_plot_number += 1
639
+ end
640
+ pause() unless opt[:nopause]
641
+ reset() unless opt[:noreset]
642
+ end
643
+
644
+ def scanvas (*argv, &block)
645
+ plots, opt = parse_args(argv, &block)
646
+ put %{
647
+ unset xtics
648
+ unset x2tics
649
+ unset ytics
650
+ unset y2tics
651
+ unset ztics
652
+ unset xlabel
653
+ unset ylabel
654
+ unset zlabel
655
+ unset x2label
656
+ unset y2label
657
+ unset key
658
+ }
659
+ opt.set(:margin, :title, :bgcolor,
660
+ :xaxis, :yaxis, :zaxis,
661
+ :border, :parametric,
662
+ :options)
663
+ put %{
664
+ splot "-" with dots
665
+ -1e30,-1e30,-1e30
666
+ e
667
+ }
668
+ if @multiplot_mode
669
+ @multiplot_plot_number += 1
670
+ end
671
+ pause() unless opt[:nopause]
672
+ reset() unless opt[:noreset]
673
+ end
674
+
675
+ #
676
+ # with csv file
677
+ # ["foo.csv","1:2","title","with","y2"]
678
+ #
679
+ def blank (*argv, &block)
680
+ plots, opt = parse_args(argv, &block)
681
+ put %{
682
+ unset xtics
683
+ unset ytics
684
+ unset x2tics
685
+ unset y2tics
686
+ unset xlabel
687
+ unset ylabel
688
+ unset x2label
689
+ unset y2label
690
+ unset border
691
+ unset key
692
+ unset grid
693
+ }
694
+ opt.set(:margin, :title, :bgcolor,
695
+ :parametric,
696
+ :options)
697
+ put %{
698
+ plot [0:1] [0:1] "-" with dots
699
+ -1,-1
700
+ e
701
+ }
702
+ if @multiplot_mode
703
+ @multiplot_plot_number += 1
704
+ end
705
+ pause() unless opt[:nopause]
706
+ reset() unless opt[:noreset]
707
+ end
708
+
709
+ #
710
+ # with csv file
711
+ # ["foo.csv","1:2","title","with","axes"]
712
+ #
713
+ # with csv string
714
+ # ["1,2\n2,3\n4,5","1:2","title","with","axes"]
715
+ #
716
+ def plot (*argv, &block)
717
+ @init.call if @init
718
+ plots, opt = parse_args(argv, &block)
719
+ @last = plots + [opt]
720
+ with_tempfile(plots.size) { |*tempfile|
721
+ plot_list = []
722
+ plots.each_with_index do |arg, i|
723
+ arg = arg.clone
724
+ local_ranges = []
725
+ loop do
726
+ case arg.first
727
+ when Range
728
+ rng = arg.shift
729
+ local_ranges << "[" + [rng.begin,rng.end].join(":") + "] "
730
+ when Hash
731
+ var,rng = arg.shift.first
732
+ case var
733
+ when :x
734
+ local_ranges[0] = "[" + [rng.begin,rng.end].join(":") + "] "
735
+ when :y
736
+ local_ranges[1] = "[" + [rng.begin,rng.end].join(":") + "] "
737
+ when :z
738
+ local_ranges[2] = "[" + [rng.begin,rng.end].join(":") + "] "
739
+ else
740
+ local_ranges << "[#{var}=" + [rng.begin,rng.end].join(":") + "] "
741
+ end
742
+ else
743
+ break
744
+ end
745
+ end
746
+ if i == 0 and not local_ranges.empty?
747
+ local_ranges.unshift "sample"
748
+ end
749
+ local_ranges = local_ranges.map{|v| v.nil? ? "[:]" : v }
750
+ if arg.first.is_a?(Symbol) and arg.first == :newhistogram
751
+ arg.shift
752
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
753
+ plot_cmd = [
754
+ "newhistogram",
755
+ using ? using : "",
756
+ title ? title : "",
757
+ with ? with : "",
758
+ ]
759
+ elsif arg.first.is_a?(DataBlock)
760
+ datablock = arg.shift
761
+ if datablock.is_csv?
762
+ put("set datafile separator ','")
763
+ end
764
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
765
+ plot_cmd = local_ranges + [
766
+ datablock.name,
767
+ dataspec ? dataspec : "",
768
+ @gnuplot_version >= 4.4 ? "volatile" : "",
769
+ opt[:using] ? "using " + opt[:using] :
770
+ using ? using : "",
771
+ axis ? "axes #{axis}" : "",
772
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
773
+ title ? "title #{title}" : ""
774
+ ]
775
+ elsif arg.first.is_a?(String)
776
+ file = arg.shift
777
+ if file =~ /\.(png|jpg)\z/
778
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
779
+ plot_cmd = local_ranges + [
780
+ "'#{file}'",
781
+ dataspec ? dataspec : "",
782
+ "binary filetype=auto",
783
+ @gnuplot_version >= 4.4 ? "volatile" : "",
784
+ opt[:using] ? "using " + opt[:using] :
785
+ using ? using : "",
786
+ axis ? "axes #{axis}" : "",
787
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
788
+ title ? "title #{title}" : ""
789
+ ]
790
+ else
791
+ if file == ""
792
+ elsif file =~ /,/ or file =~ /[\n\r]/
793
+ if file =~ /,/
794
+ put("set datafile separator ','")
795
+ end
796
+ file = file.gsub(/UNDEF/, "NaN")
797
+ open(tempfile[i], "w") { |io| io.write file }
798
+ file = tempfile[i]
799
+ else
800
+ unless File.exist?(file)
801
+ raise "can't open file #{file} for plot2d"
802
+ end
803
+ end
804
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
805
+ plot_cmd = local_ranges + [
806
+ "'#{file}'",
807
+ dataspec ? dataspec : "",
808
+ @gnuplot_version >= 4.4 ? "volatile" : "",
809
+ opt[:using] ? "using " + opt[:using] :
810
+ using ? using : "",
811
+ axis ? "axes #{axis}" : "",
812
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
813
+ title ? "title #{title}" : ""
814
+ ]
815
+ end
816
+ elsif arg.first.is_a?(Array)
817
+ funcs, dataspec, using, title, with, axis = *parse_data(arg)
818
+ plot_cmd = local_ranges + [
819
+ funcs.join(","),
820
+ dataspec ? dataspec : "",
821
+ opt[:using] ? "using " + opt[:using] :
822
+ using ? using : "",
823
+ axis ? "axes #{axis}" : "",
824
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
825
+ title ? "title #{title}" : ""
826
+ ]
827
+ else
828
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
829
+ arg = arg.map{|x| CArray.wrap_readonly(x, CA_DOUBLE) }
830
+ if with.to_s =~ /rgbimage/ or opt[:with].to_s =~ /rgbimage/
831
+ if arg[2] and arg[2].rank >= 2 and
832
+ ( arg[2].size != arg[0].size or arg[2].size != arg[1].size )
833
+ xlen = arg[0].size
834
+ ylen = arg[1].size
835
+ arg[0] = arg[0][ylen,:%]
836
+ arg[1] = arg[1][:%,xlen]
837
+ if arg[2].rank == 3
838
+ arg2 = arg[2]
839
+ arg[2] = arg2[nil,nil,0]
840
+ arg[3] = arg2[nil,nil,1]
841
+ arg[4] = arg2[nil,nil,2]
842
+ end
843
+ end
844
+ is_image = true
845
+ is_rgb = true
846
+ elsif with.to_s =~ /image/ or opt[:with].to_s =~ /image/
847
+ if arg[2] and arg[2].rank == 2 and
848
+ ( arg[2].size != arg[0].size or arg[2].size != arg[1].size )
849
+ xlen = arg[0].size
850
+ ylen = arg[1].size
851
+ arg[0] = arg[0][ylen,:%]
852
+ arg[1] = arg[1][:%,xlen]
853
+ end
854
+ is_image = true
855
+ is_rgb = false
856
+ else
857
+ arg = arg.map{|x| x.rank > 1 ? x[nil] : x }
858
+ is_image = false
859
+ end
860
+ out = CArray.merge(CA_DOUBLE, arg, -1)
861
+ if is_image
862
+ if is_rgb
863
+ datalen = out.dim2
864
+ if arg.size == 1
865
+ datalen = 1
866
+ array = "(" + [out.dim1,out.dim0].join(',') + ")"
867
+ record = nil
868
+ else
869
+ datalen = 5
870
+ array = nil
871
+ record = "(" + [out.dim1,out.dim0].join(',') + ")"
872
+ end
873
+ else
874
+ if arg.size == 1
875
+ datalen = 1
876
+ array = "(" + [out.dim1,out.dim0].join(',') + ")"
877
+ record = nil
878
+ else
879
+ datalen = 3
880
+ array = nil
881
+ record = out.dim1*out.dim0
882
+ end
883
+ end
884
+ else
885
+ datalen = arg.size
886
+ record = out.dim0
887
+ array = nil
888
+ end
889
+ open(tempfile[i], "w") { |io|
890
+ out.unmask_copy(0.0/0.0).dump_binary(io)
891
+ }
892
+ plot_cmd = local_ranges + [
893
+ "'#{tempfile[i]}'",
894
+ "binary",
895
+ record ? "record=#{record}" : "",
896
+ array ? "array=#{array}" : "",
897
+ "format='#{'%double'*datalen}'",
898
+ dataspec ? dataspec : "",
899
+ @gnuplot_version >= 4.4 ? "volatile" : "",
900
+ opt[:using] ? "using " + opt[:using] :
901
+ using ? using :
902
+ "using " + "#{(1..datalen).map{|x|'%i' % x}.join(':')}",
903
+ axis ? "axes #{axis}" : "",
904
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
905
+ title ? "title #{title}" : ""
906
+ ]
907
+ end
908
+ plot_list.push(plot_cmd.join(" "))
909
+ end
910
+ opt.set(:margin, :title, :key, :bgcolor, :palette,
911
+ :timefmt, :xaxis, :x2axis, :yaxis, :y2axis,
912
+ :cbaxis, :grid, :border, :parametric,
913
+ :options)
914
+ put("plot " + plot_list.join(","))
915
+ if @multiplot_mode
916
+ @multiplot_plot_number += 1
917
+ end
918
+ pause() unless opt[:nopause]
919
+ reset() unless opt[:noreset]
920
+ }
921
+ end
922
+
923
+ alias scatter plot
924
+ alias plot2d plot
925
+
926
+ def splot (*argv, &block)
927
+ @init.call if @init
928
+ plots, opt = parse_args(argv, &block)
929
+ @last = plots + [opt]
930
+ with_tempfile(plots.size) { |*tempfile|
931
+ plot_list = []
932
+ plots.each_with_index do |arg, i|
933
+ arg = arg.clone
934
+ local_ranges = []
935
+ loop do
936
+ case arg.first
937
+ when Range
938
+ rng = arg.shift
939
+ local_ranges << "[" + [rng.begin,rng.end].join(":") + "] "
940
+ when Hash
941
+ var,rng = arg.shift.first
942
+ case var
943
+ when :x
944
+ local_ranges[0] = "[" + [rng.begin,rng.end].join(":") + "] "
945
+ when :y
946
+ local_ranges[1] = "[" + [rng.begin,rng.end].join(":") + "] "
947
+ when :z
948
+ local_ranges[2] = "[" + [rng.begin,rng.end].join(":") + "] "
949
+ else
950
+ local_ranges << "[#{var}=" + [rng.begin,rng.end].join(":") + "] "
951
+ end
952
+ else
953
+ break
954
+ end
955
+ end
956
+ if i == 0 and not local_ranges.empty?
957
+ local_ranges.unshift "sample"
958
+ end
959
+ local_ranges = local_ranges.map{|v| v.nil? ? "[:]" : v }
960
+ if arg.first.is_a?(DataBlock)
961
+ datablock = arg.shift
962
+ if datablock.is_csv?
963
+ put("set datafile separator ','")
964
+ end
965
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
966
+ plot_cmd = local_ranges + [
967
+ datablock.name,
968
+ dataspec ? dataspec : "",
969
+ @gnuplot_version >= 4.4 ? "volatile" : "",
970
+ opt[:using] ? "using " + opt[:using] :
971
+ using ? using : "",
972
+ axis ? "axes #{axis}" : "",
973
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
974
+ title ? "title #{title}" : ""
975
+ ]
976
+ elsif arg.first.is_a?(String)
977
+ file = arg.shift
978
+ if file =~ /\.(png|jpg)\z/
979
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
980
+ plot_cmd = [
981
+ "'#{file}'",
982
+ dataspec ? dataspec : "",
983
+ "binary filetype=auto",
984
+ @gnuplot_version >= 4.4 ? "volatile" : "",
985
+ opt[:using] ? "using " + opt[:using] :
986
+ using ? using : "",
987
+ axis ? "axes #{axis}" : "",
988
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
989
+ title ? "title #{title}" : ""
990
+ ]
991
+ else
992
+ if file == ""
993
+ elsif file =~ /,/ or file =~ /[\n\r]/
994
+ if file =~ /,/
995
+ put("set datafile separator ','")
996
+ end
997
+ file = file.gsub(/UNDEF/, "NaN")
998
+ open(tempfile[i], "w") { |io| io.write file }
999
+ file = tempfile[i]
1000
+ else
1001
+ unless File.exist?(file)
1002
+ raise "can't open file #{file} for splot"
1003
+ end
1004
+ end
1005
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
1006
+ plot_cmd = [
1007
+ "'#{file}'",
1008
+ dataspec ? dataspec : "",
1009
+ @gnuplot_version >= 4.4 ? "volatile" : "",
1010
+ opt[:using] ? "using " + opt[:using] :
1011
+ using ? using : "",
1012
+ axis ? "axes #{axis}" : "",
1013
+ with ? "with #{with}"
1014
+ : opt[:with] ? "with #{opt[:with]}" : "",
1015
+ title ? "title #{title}" : ""
1016
+ ]
1017
+ end
1018
+ elsif arg.first.is_a?(Array)
1019
+ funcs, dataspec, using, title, with, axis = *parse_data(arg)
1020
+ plot_cmd = [
1021
+ funcs.join(","),
1022
+ dataspec ? dataspec : "",
1023
+ opt[:using] ? "using " + opt[:using] :
1024
+ using ? using : "",
1025
+ axis ? "axes #{axis}" : "",
1026
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
1027
+ title ? "title #{title}" : ""
1028
+ ]
1029
+ else
1030
+ arg, dataspec, using, title, with, axis = *parse_data(arg)
1031
+ arg = arg.map{|x| CArray.wrap_readonly(x, CA_DOUBLE) }
1032
+ if arg[2] and arg[2].rank == 2 and
1033
+ ( arg[2].size != arg[0].size or arg[2].size != arg[1].size )
1034
+ xlen = arg[0].size
1035
+ ylen = arg[1].size
1036
+ arg[0] = arg[0][ylen,:%]
1037
+ arg[1] = arg[1][:%,xlen]
1038
+ is_image = true
1039
+ elsif arg[0] and arg[0].rank == 2
1040
+ is_image = true
1041
+ elsif arg[0] and arg[0].rank == 3
1042
+ is_image = true
1043
+ else
1044
+ is_image = false
1045
+ end
1046
+ out = CArray.merge(CA_DOUBLE, arg, -1)
1047
+ if is_image
1048
+ datalen = out.dim2
1049
+ record = "(" + [out.dim1,out.dim0].join(",") + ")"
1050
+ else
1051
+ datalen = arg.size
1052
+ record = out.dim0
1053
+ end
1054
+ open(tempfile[i], "w") { |io|
1055
+ out.unmask_copy(0.0/0.0).dump_binary(io)
1056
+ }
1057
+ plot_cmd = local_ranges + [
1058
+ "'#{tempfile[i]}'",
1059
+ "binary",
1060
+ record ? "record=#{record}" : "",
1061
+ "format='#{'%double'*datalen}'",
1062
+ dataspec ? dataspec : "",
1063
+ @gnuplot_version >= 4.4 ? "volatile" : "",
1064
+ opt[:using] ? "using " + opt[:using] :
1065
+ using ? using :
1066
+ "using " + "#{(1..datalen).map{|x|'%i' % x}.join(':')}",
1067
+ axis ? "axes #{axis}" : "",
1068
+ with ? "with #{with}" : opt[:with] ? "with #{opt[:with]}" : "",
1069
+ title ? "title #{title}" : ""
1070
+ ]
1071
+ end
1072
+ plot_list.push(plot_cmd.join(" "))
1073
+ end
1074
+ opt.set(:margin, :title, :key, :bgcolor, :view, :palette,
1075
+ :timefmt, :xaxis, :yaxis, :zaxis,
1076
+ :cbaxis, :border, :parametric, :options)
1077
+ put("splot " + plot_list.join(","))
1078
+ if @multiplot_mode
1079
+ @multiplot_plot_number += 1
1080
+ end
1081
+ pause() unless opt[:nopause]
1082
+ reset() unless opt[:noreset]
1083
+ }
1084
+ end
1085
+
1086
+ alias scatter3d splot
1087
+ alias mesh3d splot
1088
+ alias grid3d splot
1089
+
1090
+ def image (*argv, &block)
1091
+ raise "image() will be obsolete, use plot(..., :with=>'(rgb)image')"
1092
+ end
1093
+
1094
+ def imagemap (*argv, &block)
1095
+ raise "imagemap() will be obsolete, use plot(..., :with=>'(rgb)image')"
1096
+ end
1097
+
1098
+ #
1099
+ # fit(function, params, data, options)
1100
+ #
1101
+ #
1102
+ # with csv file
1103
+ # ["foo.csv","1:2","title","with","axes"]
1104
+ #
1105
+ # with csv string
1106
+ # ["1,2\n2,3\n4,5","1:2","title","with","axes"]
1107
+ #
1108
+ def fit (expr, params, data, opt = {})
1109
+ with_tempfile(2) { |tempfile, logfile|
1110
+ if data.first.is_a?(DataBlock)
1111
+ datablock = data.shift
1112
+ if datablock.is_csv?
1113
+ put("set datafile separator ','")
1114
+ end
1115
+ using = data.shift
1116
+ fitdata = [
1117
+ datablock.name,
1118
+ using ? "using " + using :
1119
+ opt[:using] ? "using " + opt[:using] : "",
1120
+ ]
1121
+ elsif data.first.is_a?(String)
1122
+ file = data.shift
1123
+ if file =~ /,/ or file =~ /[\n\r]/
1124
+ if file =~ /,/
1125
+ put("set datafile separator ','")
1126
+ end
1127
+ open(tempfile, "w") { |io| io.write file }
1128
+ file = tempfile
1129
+ else
1130
+ unless File.exist?(file)
1131
+ raise "can't open file #{file} for plot2d"
1132
+ end
1133
+ end
1134
+ using = data.shift
1135
+ fitdata = [
1136
+ "'#{file}'",
1137
+ using ? "using " + using :
1138
+ opt[:using] ? "using " + opt[:using] : "",
1139
+ ]
1140
+ else
1141
+ arg = data.map{|x| CArray.wrap_readonly(x, CA_DOUBLE) }
1142
+ if arg[2] and arg[2].rank == 2 and
1143
+ ( arg[2].size != arg[0].size or arg[2].size != arg[1].size )
1144
+ xlen = arg[0].size
1145
+ ylen = arg[1].size
1146
+ arg[0] = arg[0][ylen,:%]
1147
+ arg[1] = arg[1][:%,xlen]
1148
+ record = arg[0].dim1
1149
+ elsif arg[0] and arg[0].rank == 2
1150
+ record = arg[0].dim1
1151
+ else
1152
+ record = arg[0].dim0
1153
+ end
1154
+ datalen = arg.size
1155
+ out = CArray.merge(CA_DOUBLE, arg, -1)
1156
+ open(tempfile, "w") { |io|
1157
+ out.unmask_copy(0.0/0.0).dump_binary(io)
1158
+ }
1159
+ fitdata = [
1160
+ "'#{tempfile}'",
1161
+ "binary",
1162
+ record ? "record=#{record}" : "",
1163
+ "format='#{'%double'*datalen}'",
1164
+ "using " + ( opt[:using] ||
1165
+ "#{(1..datalen).map{|x|'($%i)' % x}.join(':')}" ),
1166
+ ]
1167
+ end
1168
+ if opt[:ranges]
1169
+ ranges = opt[:ranges]
1170
+ else
1171
+ ranges = ""
1172
+ end
1173
+ set("fit logfile '#{logfile}' errorvariables covariancevariables")
1174
+ put("fit #{ranges} #{expr} #{fitdata.join(" ")} via " + params.map{|x| x.to_s}.join(","))
1175
+ res = OpenStruct.new
1176
+ res.expression = expr
1177
+ res.parameters = params
1178
+ result_params = put("print " + params.map{|x| x.to_s}.join(",")).split.map{|_x| _x.to_f}
1179
+ result_err = put("print " + params.map{|x| x.to_s + "_err"}.join(",")).split.map{|_x| _x.to_f}
1180
+ result_cov = put("print " + params.map{|x| params.map{|y| "FIT_COV_" + x.to_s + "_" + y.to_s }}.join(",")).split.map{|_x| _x.to_f}
1181
+ params.each_with_index do |name, i|
1182
+ res.send(name.to_s+"=", result_params[i])
1183
+ res.send(name.to_s+"_err=", result_err[i])
1184
+ end
1185
+ i=0
1186
+ params.each do |x|
1187
+ params.each do |y|
1188
+ res.send("cov_" + x.to_s + "_" + y.to_s + "=", result_cov[i])
1189
+ end
1190
+ i+=1
1191
+ end
1192
+ res.log = File.read(logfile)
1193
+ result = put("print FIT_NDF, FIT_WSSR, FIT_STDFIT, FIT_P")
1194
+ res.ndf, res.wssr, res.stdfit, res.fit_p = result.split.map{|_x| _x.to_f}
1195
+
1196
+ return result_params, res
1197
+ }
1198
+ end
1199
+
1200
+ #
1201
+ # my_palette = [[0, '#ffffff'],
1202
+ # [1, '#909090'],
1203
+ # [5, '#000090'],
1204
+ # [10, '#000fff'],
1205
+ # [25, '#0090ff'],
1206
+ # [50, '#0fffee'],
1207
+ # [75, '#90ff70'],
1208
+ # [100,'#ffee00'],
1209
+ # [200,'#ff7000'],
1210
+ # [300,'#ee0000'],
1211
+ # [400,'#7f0000']]
1212
+ # index = gp.set_palette_discrete(depth, my_palette)
1213
+ def set_palette_discrete (data, my_palette, option = {})
1214
+ default = { :model=>"RGB",
1215
+ :continuous=>false,
1216
+ :lower=>nil,
1217
+ :upper=>nil,
1218
+ :lower_label=>false,
1219
+ :upper_label=>false }
1220
+ option = default.update(option)
1221
+ model, continuous, lower, lower_label, upper, upper_label =
1222
+ option.values_at(:model, :continuous, :lower, :lower_label, :upper, :upper_label)
1223
+ levels = my_palette.size
1224
+ scale = my_palette.map{|r| r[0] }
1225
+ scalec = scale.clone
1226
+ color = my_palette.map{|r| r[1] }
1227
+ out = []
1228
+ cbmin = 0
1229
+ cbmax = levels - 1
1230
+ maxcolors = levels-1
1231
+ if continuous
1232
+ if lower
1233
+ out << [-1, %{'#{lower}'}]
1234
+ cbmin = -1
1235
+ maxcolors += 1
1236
+ end
1237
+ (levels).times do |i|
1238
+ level = i
1239
+ out << [level, %{'#{color[i]}'}]
1240
+ end
1241
+ if upper
1242
+ out << [levels, %{'#{upper}'}]
1243
+ cbmax = levels
1244
+ maxcolors += 1
1245
+ end
1246
+ else
1247
+ if lower
1248
+ out << [-1, %{'#{lower}'}]
1249
+ out << [0, %{'#{lower}'}]
1250
+ cbmin = -1
1251
+ maxcolors += 1
1252
+ end
1253
+ (levels-1).times do |i|
1254
+ level = i
1255
+ level1 = i+1
1256
+ out << [level, %{'#{color[i]}'}]
1257
+ out << [level1, %{'#{color[i]}'}]
1258
+ end
1259
+ if upper
1260
+ out << [levels-1, %{'#{upper}'}]
1261
+ out << [levels, %{'#{upper}'}]
1262
+ cbmax = levels
1263
+ maxcolors += 1
1264
+ end
1265
+ end
1266
+ put ["set palette model #{model} maxcolors #{maxcolors} defined (\\",
1267
+ out.map{|list| " " + list.join(" ")}.join(",\\\n") + "\\",
1268
+ ")"].join("\n")
1269
+ out = []
1270
+ if lower and lower_label
1271
+ out << [%{''{/Symbol <}#{scale.first}'}, cbmin]
1272
+ end
1273
+ scale.each_with_index do |s, i|
1274
+ out << [%{'#{s}'}, i]
1275
+ end
1276
+ if upper and upper_label
1277
+ out << [%{'{/Symbol \\263}#{scale.last}'}, cbmax]
1278
+ end
1279
+ put %{ set cbtics (#{out.map {|d| d.join(" ")}.join(",")}) }
1280
+ put %{ set cbrange [#{cbmin}:#{cbmax}] }
1281
+ return CA_DOUBLE(scale).section(data)
1282
+ end
1283
+
1284
+ #
1285
+ def set_xtics_monthly (start, last, fmt = nil, interval=nil, linewidth = 1, style = "lc rgb 'black' back")
1286
+ unless fmt
1287
+ fmt = "%b"
1288
+ end
1289
+ unless interval
1290
+ interval = 3
1291
+ end
1292
+ case start
1293
+ when String
1294
+ start = DateTime.parse(start)
1295
+ end
1296
+ case last
1297
+ when String
1298
+ last = DateTime.parse(last)
1299
+ end
1300
+ if interval < 0
1301
+ start = DateTime.parse(start.strftime("%Y-%m-01")) + 0.5
1302
+ last = (DateTime.parse(last.strftime("%Y-%m-01"))) + 0.5 >> 1
1303
+ else
1304
+ start = DateTime.parse(start.strftime("%Y-%m-01"))
1305
+ last = (DateTime.parse(last.strftime("%Y-%m-01"))) >> 1
1306
+ end
1307
+ set %{ xrange [#{time(start)}:#{time(last)}] }
1308
+ if linewidth > 0
1309
+ set %{ xtics ("" 0) scale 0,2 mirror }
1310
+ set %{ x2tics ("" 0) scale 0,1 mirror }
1311
+ else
1312
+ set %{ xtics ("" 0) scale 0,0 mirror }
1313
+ set %{ x2tics ("" 0) scale 0,0 mirror }
1314
+ end
1315
+ d = start
1316
+ while d <= last
1317
+ set %{ xtics add ('' #{time(d)} 1) }
1318
+ set %{ xtics add ('#{d.strftime(fmt)}' #{time(d+15)} 0) }
1319
+ case interval
1320
+ when -2,2
1321
+ set %{ x2tics add ('' #{time(d+15)} 1) }
1322
+ when -3,3
1323
+ set %{ x2tics add ('' #{time(d+10)} 1) }
1324
+ set %{ x2tics add ('' #{time(d+20)} 1) }
1325
+ when -6,6
1326
+ set %{ x2tics add ('' #{time(d+5)} 1) }
1327
+ set %{ x2tics add ('' #{time(d+10)} 1) }
1328
+ set %{ x2tics add ('' #{time(d+15)} 1) }
1329
+ set %{ x2tics add ('' #{time(d+20)} 1) }
1330
+ set %{ x2tics add ('' #{time(d+25)} 1) }
1331
+ else
1332
+ end
1333
+ d >>= 1
1334
+ end
1335
+ if linewidth > 0
1336
+ d = start >> 1
1337
+ while d < last
1338
+ set %{ arrow nohead from #{time(d)}, graph 0
1339
+ rto graph 0, graph 1 #{style} }
1340
+ d >>= 1
1341
+ end
1342
+ end
1343
+ end
1344
+
1345
+ class DataBlock
1346
+
1347
+ @@datablock_count = 0
1348
+
1349
+ def initialize (processor, *args)
1350
+ put_ok = false
1351
+ if args.size == 1 and args.first.is_a?(Symbol)
1352
+ @name = "$" + args.first.to_s
1353
+ @text = processor.put %{ print #{@name}}
1354
+ elsif args.size == 1 and args.first.is_a?(String)
1355
+ @@datablock_count += 1
1356
+ @name = "$DBLK_#{@@datablock_count}"
1357
+ @text = args.first.dup
1358
+ put_ok = true
1359
+ else
1360
+ @@datablock_count += 1
1361
+ @name = "$DBLK_#{@@datablock_count}"
1362
+ @text = CArray.join(*args).to_csv
1363
+ @text.gsub!(/UNDEF/,"NaN")
1364
+ put_ok = true
1365
+ end
1366
+ @text.strip!
1367
+ @text.chomp!
1368
+ if put_ok
1369
+ processor.put %{
1370
+ #{@name} <<__EOD__
1371
+ #{@text}
1372
+ __EOD__
1373
+ }
1374
+ end
1375
+ end
1376
+
1377
+ def is_csv?
1378
+ return (@text =~ /,/)
1379
+ end
1380
+
1381
+ def to_s
1382
+ return @text.dup
1383
+ end
1384
+
1385
+ def to_ca
1386
+ data = []
1387
+ @text.each_line do |line|
1388
+ case line
1389
+ when /^#/
1390
+ else
1391
+ data << line.strip.split(/ +/)
1392
+ end
1393
+ end
1394
+ return CA_OBJECT(data)
1395
+ end
1396
+
1397
+ attr_reader :name, :text
1398
+
1399
+ end
1400
+
1401
+ def datablock (*args)
1402
+ return DataBlock.new(self, *args)
1403
+ end
1404
+
1405
+ class Option # :nodoc:
1406
+
1407
+ def initialize (processor, option)
1408
+ @processor = processor
1409
+ @o = option
1410
+ end
1411
+
1412
+ def set (*names)
1413
+ names.each do |name|
1414
+ self.send("set_#{name}")
1415
+ end
1416
+ end
1417
+
1418
+ def [] (name)
1419
+ @o[name]
1420
+ end
1421
+
1422
+ def []= (name, value)
1423
+ @o[name] = value
1424
+ end
1425
+
1426
+ def update (hash)
1427
+ @o.update(hash)
1428
+ end
1429
+
1430
+ private
1431
+
1432
+ def put (*lines)
1433
+ return @processor.put(*lines)
1434
+ end
1435
+
1436
+ def evaluate (expr)
1437
+ return @processor.evaluate(expr)
1438
+ end
1439
+
1440
+ def set_title
1441
+ textcolor = @o[:fgcolor] ? "textcolor rgb \"#{@o[:fgcolor]}\"" : ""
1442
+ if @o[:title]
1443
+ put('set title "' + @o[:title] + '" ' + textcolor)
1444
+ end
1445
+ end
1446
+
1447
+ def set_key
1448
+ # ver = evaluate("GPVAL_VERSION")
1449
+ # if ver.to_f <= 4.2
1450
+ # tc = ""
1451
+ # else
1452
+ # tc = @o[:fgcolor] ? "tc rgb \"#{@o[:fgcolor]}\"" : ""
1453
+ # end
1454
+ # put("set key #{tc}")
1455
+ end
1456
+
1457
+ def set_bgcolor
1458
+ if @o[:framecolor]
1459
+ put "set object rect from screen 0, screen 0 " \
1460
+ "to screen 1, screen 1 behind " \
1461
+ "fc rgb '#{@o[:framecolor]}' " \
1462
+ "fillstyle solid 1.0 noborder"
1463
+ end
1464
+ if @o[:shadowcolor]
1465
+ put "set object rect from graph 0.01, graph -0.02 " \
1466
+ "to graph 1.01, graph 0.98 behind " \
1467
+ "fc rgb '#{@o[:shadowcolor]}' " \
1468
+ "fillstyle solid 1.0 noborder"
1469
+ end
1470
+ if @o[:bgcolor]
1471
+ put "set object rect from graph 0, graph 0 " \
1472
+ "to graph 1, graph 1 behind " \
1473
+ "fc rgb '#{@o[:bgcolor]}' " \
1474
+ "fillstyle solid 1.0 noborder"
1475
+ end
1476
+ end
1477
+
1478
+ def set_border
1479
+ if @o[:noborder]
1480
+ put("unset border")
1481
+ end
1482
+ if @o[:noaxis]
1483
+ put("unset xtics")
1484
+ put("unset ytics")
1485
+ put("unset ztics")
1486
+ put("unset xlabel")
1487
+ put("unset ylabel")
1488
+ put("unset zlabel")
1489
+ return
1490
+ end
1491
+ if @o[:fgcolor]
1492
+ put("set border linecolor rgb \"#{@o[:fgcolor]}\" ")
1493
+ if @o[:zeroaxis]
1494
+ put("set xzeroaxis linecolor rgb \"#{@o[:fgcolor]}\" ")
1495
+ put("set yzeroaxis linecolor rgb \"#{@o[:fgcolor]}\" ")
1496
+ end
1497
+ else
1498
+ if @o[:zeroaxis]
1499
+ put("set xzeroaxis",
1500
+ "set yzeroaxis")
1501
+ end
1502
+ end
1503
+ end
1504
+
1505
+ def set_axis(axis)
1506
+ label, range, fmt, tics, mtics, ticsopts = *@o[axis]
1507
+ logscale = @o["#{axis}log".intern]
1508
+ timescale = @o["#{axis}time".intern]
1509
+ reverse = @o["#{axis}reverse".intern]
1510
+ textcolor = @o[:fgcolor] ? "textcolor rgb \"#{@o[:fgcolor]}\"" : ""
1511
+ if label
1512
+ put("set #{axis}label " + %{ "#{label} "} + textcolor)
1513
+ else
1514
+ put("unset #{axis}label")
1515
+ end
1516
+ if timescale
1517
+ put("set #{axis}data time")
1518
+ end
1519
+ if range
1520
+ case range
1521
+ when Range
1522
+ put("set #{axis}range [" + [range.begin,range.end].join(":") + "] " +
1523
+ ( reverse ? "reverse " : "" ))
1524
+ when Array
1525
+ srange = range.join(":")
1526
+ put("set #{axis}range [" + srange + "] " + ( reverse ? "reverse " : "" ))
1527
+ else
1528
+ raise "invalid range specification"
1529
+ end
1530
+ else
1531
+ if reverse
1532
+ put("set #{axis}range [*:*] reverse")
1533
+ end
1534
+ end
1535
+ if tics
1536
+ if tics.is_a?(Array)
1537
+ ticslist = tics.collect do |v|
1538
+ v = [v].flatten
1539
+ case v.size
1540
+ when 1
1541
+ v.first.to_s
1542
+ else
1543
+ ['"'+v[1].to_s+'"', v[0], v[2]||0].join(" ")
1544
+ end
1545
+ end.join(",")
1546
+ put("set #{axis}tics (#{ticslist}) #{textcolor} #{ticsopts}")
1547
+ else
1548
+ put("set #{axis}tics #{tics} #{textcolor} #{ticsopts}")
1549
+ end
1550
+ else
1551
+ put("set #{axis}tics #{textcolor} #{ticsopts}")
1552
+ end
1553
+ if mtics
1554
+ put("set m#{axis}tics #{mtics}")
1555
+ end
1556
+ if fmt
1557
+ put(%{ set format #{axis} "#{fmt}"})
1558
+ end
1559
+ if logscale
1560
+ put("set logscale #{axis}")
1561
+ end
1562
+ end
1563
+
1564
+ def set_xaxis
1565
+ set_axis(:x)
1566
+ end
1567
+
1568
+ def set_yaxis
1569
+ set_axis(:y)
1570
+ end
1571
+
1572
+ def set_x2axis
1573
+ if @o[:x2]
1574
+ set_axis(:x2)
1575
+ end
1576
+ end
1577
+
1578
+ def set_y2axis
1579
+ if @o[:y2]
1580
+ set_axis(:y2)
1581
+ end
1582
+ end
1583
+
1584
+ def set_zaxis
1585
+ set_axis(:z)
1586
+ end
1587
+
1588
+ def set_cbaxis
1589
+ set_axis(:cb)
1590
+ end
1591
+
1592
+ def set_grid
1593
+ if @o[:grid]
1594
+ linecolor = @o[:fgcolor] ? "linecolor rgb \"#{@o[:fgcolor]}\"" : ""
1595
+ case @o[:grid]
1596
+ when Array
1597
+ tics = @o[:grid].map{|a| "#{a}tics" }.join(" ")
1598
+ put("set grid #{tics} back linetype 0 #{linecolor}")
1599
+ else
1600
+ put("set grid xtics ytics y2tics back linetype 0 #{linecolor}")
1601
+ end
1602
+ end
1603
+ end
1604
+
1605
+ def set_options
1606
+ if @o[:ratio]
1607
+ put("set size ratio #{@o[:ratio]}")
1608
+ # put("set view equal xy")
1609
+ end
1610
+ end
1611
+
1612
+ def set_timefmt
1613
+ if @o[:timefmt]
1614
+ put("set timefmt \"#{@o[:timefmt]}\"")
1615
+ end
1616
+ end
1617
+
1618
+ def set_view
1619
+ if @o[:view]
1620
+ put("set view #{[@o[:view]].flatten.join(",")}")
1621
+ end
1622
+ end
1623
+
1624
+ def set_parametric
1625
+ if @o[:parametric]
1626
+ put("set parametric")
1627
+ end
1628
+ end
1629
+
1630
+ def set_margin
1631
+ if @o[:floating] or
1632
+ ( @processor.multiplot_mode and
1633
+ ( @processor.multiplot_option[:layout] or
1634
+ @processor.multiplot_option[:floating] ) )
1635
+ if @o[:nomargin]
1636
+ put("set lmargin 0",
1637
+ "set rmargin 0",
1638
+ "set tmargin 0",
1639
+ "set bmargin 0")
1640
+ end
1641
+ else
1642
+ put("set size 0.7, 0.7",
1643
+ "set origin 0.15, 0.15",
1644
+ "set lmargin 0",
1645
+ "set rmargin 0",
1646
+ "set tmargin 0",
1647
+ "set bmargin 0")
1648
+ end
1649
+ end
1650
+
1651
+ def set_palette (*argv)
1652
+ case @o[:palette]
1653
+ when Array
1654
+ list = @o[:palette].clone
1655
+ kind = list.shift
1656
+ Palette.set(@processor, kind.intern, *list)
1657
+ else
1658
+ Palette.set(@processor, @o[:palette])
1659
+ end
1660
+ end
1661
+
1662
+ end
1663
+
1664
+ def palette (kind, *argv)
1665
+ return Palette.set(self, kind, *argv)
1666
+ end
1667
+
1668
+ module Palette
1669
+
1670
+ def self.quote (text)
1671
+ case text
1672
+ when Symbol
1673
+ text.to_s
1674
+ when /^\{\{(.*)\}\}$/
1675
+ $1
1676
+ else
1677
+ text = text.clone
1678
+ if text[0, 1] == "\\"
1679
+ text[1..-1]
1680
+ else
1681
+ text.gsub!(/\n/, '\\n')
1682
+ text.gsub!(/\t/, '\\t')
1683
+ text.gsub!(/"/, '\\\\"')
1684
+ '"' + text + '"'
1685
+ end
1686
+ end
1687
+ end
1688
+
1689
+ def self.set (gp, kind, *argv)
1690
+ if argv.last.is_a?(Hash)
1691
+ opt = argv.pop
1692
+ else
1693
+ opt = {}
1694
+ end
1695
+ if opt[:model]
1696
+ gp.set %{ palette model #{opt[:model]} }
1697
+ end
1698
+ if opt[:maxcolors]
1699
+ gp.set %{ palette maxcolors #{opt[:maxcolors]} }
1700
+ end
1701
+ case kind
1702
+ when :defined
1703
+ self.set_palette_array(gp, argv)
1704
+ when :random
1705
+ n = argv.first || 10
1706
+ list = []
1707
+ n.times do |i|
1708
+ value = rand(256)*0x10000 + rand(256)*0x100 + rand(256)
1709
+ list << [i, "#%6x" % value]
1710
+ end
1711
+ self.set_palette_array(gp, list)
1712
+ when :rgbformulae
1713
+ set_palette_formula(gp, *argv[0,3])
1714
+ when :file
1715
+ set_palette_file(gp, argv.first)
1716
+ when :gmt
1717
+ set_palette_gmt(gp, argv.first, opt)
1718
+ when :cpt_city
1719
+ set_palette_cpt_city(gp, argv.first, opt)
1720
+ when Symbol
1721
+ set_palette_predefined(gp, kind)
1722
+ when String
1723
+ set_palette_string(gp, kind)
1724
+ when CArray
1725
+ set_palette_carray(gp, kind)
1726
+ when Array
1727
+ self.set_palette_array(gp, kind)
1728
+ when ColorPalette
1729
+ set_palette_color_palette(gp, kind)
1730
+ end
1731
+ end
1732
+
1733
+ def self.set_palette_formula (gp, *argv)
1734
+ gp.set 'palette rgbformulae ' + argv.join(', ')
1735
+ end
1736
+
1737
+ def self.set_palette_file (gp, *argv)
1738
+ gp.set 'palette file ' + quote(argv[0]) + " " + argv[1].to_s
1739
+ end
1740
+
1741
+ def self.set_palette_string (gp, string)
1742
+ gp.set "palette " + string
1743
+ end
1744
+
1745
+ def self.set_palette_array (gp, array)
1746
+ gp.set "palette " +
1747
+ 'defined (' + array.map { |x|
1748
+ case x[1]
1749
+ when String
1750
+ [x[0], quote(x[1])].join(' ')
1751
+ else
1752
+ x.join(' ')
1753
+ end
1754
+ }.join(', ') + ')'
1755
+ end
1756
+
1757
+ def self.set_palette_carray (gp, ca)
1758
+ gp.instance_exec {
1759
+ with_tempfile(1) { |tmpfile|
1760
+ open(tmpfile, "w") {|io| ca.dump_binary(io)}
1761
+ if ca.rank == 1 or ( ca.rank == 2 and ca.dim1 == 1)
1762
+ set("palette file '#{tmpfile}' binary record=#{ca.dim0} using 1:1:1 model #{model}")
1763
+ elsif ca.rank == 2 and ca.dim1 == 3
1764
+ set("palette file '#{tmpfile}' binary record=#{ca.dim0} using 1:2:3 model #{model}")
1765
+ else
1766
+ raise "invalid palette specification"
1767
+ end
1768
+ }
1769
+ }
1770
+ end
1771
+
1772
+ def self.set_palette_color_palette (gp, pal)
1773
+ gp.put(pal.to_gnuplot)
1774
+ end
1775
+
1776
+ def self.set_palette_gmt (gp, name, opt)
1777
+ cpt = ColorPalette::CPT(name, :continuous=>opt[:continuous])
1778
+ if opt[:use_scale]
1779
+ min, max = cpt.min, cpt.max
1780
+ gp.set %{ cbrange [#{min}:#{max}] }
1781
+ end
1782
+ gp.put(cpt.to_gnuplot)
1783
+ end
1784
+
1785
+ def self.set_palette_cpt_city (gp, name, opt)
1786
+ file = File.expand_path(File.join(ENV["CPTCITY"],name) + ".cpt")
1787
+ cpt = ColorPalette::CPT(file, :continuous=>opt[:continuous])
1788
+ if opt[:use_scale]
1789
+ min, max = cpt.min, cpt.max
1790
+ gp.set %{ cbrange [#{min}:#{max}] }
1791
+ end
1792
+ gp.put(cpt.to_gnuplot)
1793
+ end
1794
+
1795
+ def self.set_palette_predefined (gp, name)
1796
+ case name.to_s
1797
+ when "gray"
1798
+ gp.set %{ palette defined (0 "#FFFFFF", \
1799
+ 1 "#000000") }
1800
+ when "gray_inv"
1801
+ gp.set %{ palette defined (0 "#000000", \
1802
+ 1 "#FFFFFF") }
1803
+ when "rainbow"
1804
+ gp.set %{ palette rgbformulae 22,13,-31 }
1805
+ when "polar"
1806
+ gp.set %{ palette defined (-1 "blue", \
1807
+ 0 "white", \
1808
+ 1 "red") }
1809
+ when "jet"
1810
+ gp.set %{ palette defined (0 "#00007F", \
1811
+ 0.125 "#0000FF", \
1812
+ 0.375 "#FFFFFF", \
1813
+ 0.625 "#FFFF00", \
1814
+ 0.875 "#FF0000", \
1815
+ 1 "#7F0000") }
1816
+ when "split"
1817
+ gp.set %{ palette defined (-1.0 "#7F7FFF", \
1818
+ -0.5 "#000080", \
1819
+ 0.0 "#000000", \
1820
+ 0.5 "#800000", \
1821
+ 1.0 "#FF7F7F" ) }
1822
+ when "green_metal"
1823
+ gp.set %{ palette defined ( 0.0 "#000000", \
1824
+ 0.5263 "#8D8D6C", \
1825
+ 0.6842 "#92BDBE", \
1826
+ 1.0 "#FFFFFF" )}
1827
+ when "matlab"
1828
+ gp.set %{ palette defined ( 0 '#000090', \
1829
+ 1 '#000fff', \
1830
+ 2 '#0090ff', \
1831
+ 3 '#0fffee', \
1832
+ 4 '#90ff70', \
1833
+ 5 '#ffee00', \
1834
+ 6 '#ff7000', \
1835
+ 7 '#ee0000', \
1836
+ 8 '#7f0000')}
1837
+ when "matlabw"
1838
+ gp.set %{ palette defined ( 0 'white',
1839
+ 0.01 '#000090', \
1840
+ 1 '#000fff', \
1841
+ 2 '#0090ff', \
1842
+ 3 '#0fffee', \
1843
+ 4 '#90ff70', \
1844
+ 5 '#ffee00', \
1845
+ 6 '#ff7000', \
1846
+ 7 '#ee0000', \
1847
+ 8 '#7f0000')}
1848
+ else
1849
+ raise "Unknown palette name"
1850
+ end
1851
+ end
1852
+
1853
+
1854
+ end
1855
+
1856
+ class ColorPalette # :nodoc:
1857
+
1858
+ def initialize (model, levels, color, scale = nil, continuous = false)
1859
+ @model = model
1860
+ @levels = levels
1861
+ @color = color
1862
+ @scale = scale || CArray.int(levels).seq!
1863
+ @continuous = continuous
1864
+ end
1865
+
1866
+ attr_reader :scale, :colors
1867
+
1868
+ def min
1869
+ return @scale.min
1870
+ end
1871
+
1872
+ def max
1873
+ return @scale.max
1874
+ end
1875
+
1876
+ def range
1877
+ return @scale.min..@scale.max
1878
+ end
1879
+
1880
+ def to_gnuplot
1881
+ out = []
1882
+ maxcolors = 1024
1883
+ if @continuous
1884
+ (@levels).times do |i|
1885
+ level = @scale[i]
1886
+ out.push([level, *@color[i,nil].to_a])
1887
+ end
1888
+ else
1889
+ (@levels-1).times do |i|
1890
+ level = @scale[i]
1891
+ level1 = @scale[i+1]
1892
+ out.push([level, *@color[i,nil].to_a])
1893
+ out.push([level1, *@color[i,nil].to_a])
1894
+ end
1895
+ maxcolors = @levels-1
1896
+ end
1897
+ return ["set palette model #{@model} maxcolors #{maxcolors} defined (\\",
1898
+ out.map{|list| " " + list.join(" ")}.join(",\\\n") + "\\",
1899
+ ")"].join("\n")
1900
+ end
1901
+
1902
+ end
1903
+
1904
+ class ColorPalette
1905
+
1906
+ def self.CPT (file, opt = nil)
1907
+ options = {:continuous => false}.update(opt)
1908
+ continuous = options[:continuous]
1909
+ if File.exist?(file)
1910
+ text = File.read(file)
1911
+ else
1912
+ if continuous
1913
+ text = IO.popen("makecpt -C#{file} -Z", "r") { |io| io.read }
1914
+ else
1915
+ text = IO.popen("makecpt -C#{file}", "r") { |io| io.read }
1916
+ end
1917
+ if text =~ /\A\s*\Z/
1918
+ raise "failed to makecpt #{file}"
1919
+ end
1920
+ end
1921
+
1922
+ lines = text.split("\n").map{|line| line.strip }
1923
+
1924
+ model = "RGB"
1925
+ entries = []
1926
+ lines.each do |line|
1927
+ case line
1928
+ when /\A\#\s*COLOR_MODEL\s*=\s*\+(.+)\s*\Z/
1929
+ model = $1.upcase
1930
+ when /\A\Z/, /\A#/, /\A([FBN])\s*(.*)\Z/
1931
+ next
1932
+ else
1933
+ entries.push(line.split(/\s+/)[0,8].map{|x| x.to_f})
1934
+ end
1935
+ end
1936
+
1937
+ levels = entries.size * 2
1938
+ color = CArray.float(levels, 3)
1939
+ scale = CArray.float(levels)
1940
+ level = 0
1941
+ entries.each do |entry|
1942
+ scale[level] = entry[0]
1943
+ color[level, nil] = entry[1, 3]
1944
+ level += 1
1945
+ scale[level] = entry[4]
1946
+ color[level, nil] = entry[5, 3]
1947
+ level += 1
1948
+ end
1949
+
1950
+ if model =~ /HSV/
1951
+ color[nil, 0] /= 360
1952
+ else
1953
+ color[] /= 255
1954
+ end
1955
+
1956
+ return ColorPalette.new(model, levels, color, scale, options[:contiuous])
1957
+ end
1958
+
1959
+ def self.GMT (file, continuous = true)
1960
+ return CPT(file, :continuous=>continuous)
1961
+ end
1962
+ end
1963
+
1964
+ end
1965
+
1966
+ class ColorPalette < CA::Gnuplot::ColorPalette
1967
+ end
1968
+
1969
+ class CA::Gnuplot
1970
+
1971
+ def pi2arc (th0, th1)
1972
+ return format("%f:%f", -th1+90, -th0+90)
1973
+ end
1974
+
1975
+ def xtics_histogram (ticslabels)
1976
+ max = ticslabels.size - 1
1977
+ return -0.5..max+0.5,
1978
+ (0..max).map{|k|[k,ticslabels[k]]} + (0..max-1).map{|k|[k+0.5,"",1]}
1979
+ end
1980
+
1981
+ def guide_with_x11 (*arg)
1982
+ @pause_mouse_mode = arg
1983
+ @pause_mouse_term = "x11"
1984
+ __guide__
1985
+ end
1986
+
1987
+ def guide_with_wxt (*arg)
1988
+ @pause_mouse_mode = arg
1989
+ @pause_mouse_term = "wxt"
1990
+ __guide__
1991
+ end
1992
+
1993
+ def __guide__
1994
+ guides = []
1995
+ @pause_mouse_mode.each do |mode|
1996
+ guide = ""
1997
+ if mode.to_s[-1,1] == "!"
1998
+ confirm = true
1999
+ mode = mode.to_s[0..-2].intern
2000
+ else
2001
+ confirm = false
2002
+ end
2003
+ loop do
2004
+ begin
2005
+ put %{
2006
+ set term push
2007
+ set term #{@pause_mouse_term}
2008
+ replot
2009
+ }
2010
+ case mode
2011
+ when :click
2012
+ puts "Wait mouse: 1-mouse click required"
2013
+ put "pause mouse"
2014
+ mx = evaluate "MOUSE_X"
2015
+ my = evaluate "MOUSE_Y"
2016
+ when :point
2017
+ puts "Draw point: 1-mouse click required"
2018
+ put "pause mouse"
2019
+ mx = evaluate "MOUSE_X"
2020
+ my = evaluate "MOUSE_Y"
2021
+ guide = %{set %{ label "" at #{mx},#{my} point }}
2022
+ set %{ label "" at #{mx},#{my} point pt 7 ps 2 }
2023
+ put %{ refresh }
2024
+ when :label, :clabel, :llabel, :rlabel
2025
+ puts "Draw label: 1-mouse click required"
2026
+ put "pause mouse"
2027
+ mx = evaluate "MOUSE_X"
2028
+ my = evaluate "MOUSE_Y"
2029
+ print "label text: "
2030
+ STDOUT.flush
2031
+ text = STDIN.gets.chomp
2032
+ case mode
2033
+ when :label, :llabel
2034
+ just = "left"
2035
+ when :clabel
2036
+ just = "center"
2037
+ when :rlabel
2038
+ just = "right"
2039
+ end
2040
+ guide = %{set %{ label #{text.dump} at #{"%.5g" % mx},#{"%.5g" %my} #{just} }}
2041
+ set %{ label #{text.dump} at #{mx},#{my} #{just} }
2042
+ put %{ refresh }
2043
+ when :arrow
2044
+ puts "Draw arrow: finish with right click"
2045
+ guide = ""
2046
+ pairs = []
2047
+ i = 0
2048
+ loop do
2049
+ put "pause mouse"
2050
+ mx = evaluate "MOUSE_X"
2051
+ my = evaluate "MOUSE_Y"
2052
+ mb = evaluate "MOUSE_BUTTON"
2053
+ pairs << [mx, my]
2054
+ if i >= 1
2055
+ if i == 1
2056
+ head = ""
2057
+ else
2058
+ head = "nohead"
2059
+ end
2060
+ mx1,my1 = pairs[i-1]
2061
+ mx2,my2 = pairs[i]
2062
+ guide << %{set %{ arrow from #{"%.5g" % mx2},#{"%.5g" % my2} to #{"%.5g" % mx1},#{"%.5g" % my1} #{head}} } << "\n"
2063
+ set %{ arrow from #{"%.5g" % mx2},#{"%.5g" % my2} to #{"%.5g" % mx1},#{"%.5g" % my1} #{head}}
2064
+ put %{ refresh }
2065
+ end
2066
+ if mb == "3"
2067
+ break
2068
+ end
2069
+ i += 1
2070
+ end
2071
+ when :key
2072
+ puts "Draw key: 1-mouse click required"
2073
+ put "pause mouse"
2074
+ mx = evaluate "MOUSE_X"
2075
+ my = evaluate "MOUSE_Y"
2076
+ guide = %{set %{ key at #{"%.5g" % mx},#{"%.5g" % my} }}
2077
+ set %{ key at #{mx},#{my} }
2078
+ put %{ refresh }
2079
+ else
2080
+ raise "invalid pause_mouse_mode #{@pause_mouse_mode}"
2081
+ end
2082
+ terminal %{ pop }
2083
+ if @output
2084
+ output @output
2085
+ end
2086
+ put %{ replot }
2087
+ unset %{ output }
2088
+ if confirm
2089
+ print "ok? (Y/n) "
2090
+ STDOUT.flush
2091
+ begin
2092
+ curstty = %x{stty -g}
2093
+ system "stty raw -echo -icanon isig"
2094
+ c = STDIN.getc;
2095
+ ensure
2096
+ system "stty #{curstty}"
2097
+ end
2098
+ puts
2099
+ if c == ?N or c == ?n
2100
+ raise
2101
+ end
2102
+ end
2103
+ break
2104
+ rescue
2105
+ retry
2106
+ end
2107
+ end
2108
+ guides << guide
2109
+ end
2110
+ @pause_mouse_mode = nil
2111
+ puts guides.join("\n")
2112
+ pause
2113
+ end
2114
+
2115
+
2116
+ end