ruby-gr 0.0.16 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -63,6 +63,7 @@ module GR
63
63
  try_extern 'void gr_settextcolorind(int)'
64
64
  try_extern 'void gr_inqtextcolorind(int *)'
65
65
  try_extern 'void gr_setcharheight(double)'
66
+ try_extern 'void gr_inqcharheight(double *)'
66
67
  try_extern 'void gr_setcharup(double, double)'
67
68
  try_extern 'void gr_settextpath(int)'
68
69
  try_extern 'void gr_settextalign(int, int)'
@@ -196,6 +197,10 @@ module GR
196
197
  try_extern 'void gr_inqwindow3d(double *, double *, double *, double *, double *, double *)'
197
198
  try_extern 'void gr_setscalefactors3d(double, double, double)'
198
199
  try_extern 'void gr_inqscalefactors3d(double *, double *, double *)'
199
- try_extern 'void gr_transformationinterfaceforrepl(double, double, double, double)'
200
+ try_extern 'void gr_setspace3d(double, double, double, double)'
201
+ try_extern 'void gr_text3d(double, double, double, char *, int axis)'
202
+ try_extern 'void gr_inqtext3d(double, double, double, char *, int axis, double *, double *)'
203
+ try_extern 'void gr_settextencoding(int)'
204
+ try_extern 'void gr_inqtextencoding(int *)'
200
205
  end
201
206
  end
@@ -37,59 +37,59 @@ module GR
37
37
  volume].freeze # the name might be changed in the future.
38
38
 
39
39
  # Keyword options conform to GR.jl.
40
- KW_ARGS = %i[accelerate algorithm alpha backgroundcolor barwidth baseline
41
- clabels color colormap figsize horizontal isovalue label labels
42
- levels location nbins rotation size tilt title where xflip
43
- xform xlabel xlim xlog yflip ylabel ylim ylog zflip zlabel zlim
44
- zlog clim subplot].freeze
40
+ KW_ARGS = %i[accelerate algorithm alpha ax backgroundcolor barwidth baseline
41
+ clabels clear clim color colormap crange figsize grid horizontal
42
+ isovalue kind label labels levels location nbins ratio rotation
43
+ scale size spec subplot tilt title update xaxis xflip xform
44
+ xlabel xlim xlog xrange xticks yaxis yflip ylabel ylim ylog
45
+ zflip yrange yticks viewport vp where window zaxis zlabel zlim
46
+ zlog zrange zticks].freeze
45
47
 
46
48
  @last_plot = nil
47
49
  class << self
48
50
  attr_accessor :last_plot
49
51
  end
50
52
 
51
- def initialize(*args)
52
- @kvs = if args[-1].is_a? Hash
53
- args.pop
54
- else
55
- {}
56
- end
53
+ attr_accessor :args, :kvs, :scheme
54
+
55
+ def initialize(*raw_args)
56
+ @kvs = raw_args.last.is_a?(Hash) ? raw_args.pop : {}
57
+ @args = plot_args(raw_args) # method name is the same as Julia/Python
58
+
57
59
  # Check keyword options.
58
- @kvs.each_key do |k|
59
- warn "Unknown keyword: #{k}" unless KW_ARGS.include? k
60
- end
60
+ kvs.each_key { |k| warn "Unknown keyword: #{k}" unless KW_ARGS.include? k }
61
61
 
62
62
  # label(singular form) is a original keyword arg which GR.jl does not have.
63
- @kvs[:labels] = [@kvs[:label]] if @kvs[:label] && @kvs[:labels].nil?
64
-
65
- @args = plot_args(args) # method name is the same as Julia/Python
66
- @kvs[:size] ||= [600, 450]
67
- @kvs[:ax] = false if @kvs[:ax].nil?
68
- @kvs[:subplot] ||= [0, 1, 0, 1]
69
- @kvs[:clear] = true if @kvs[:clear].nil?
70
- @kvs[:update] = true if @kvs[:update].nil?
71
- @scheme = 0
63
+ kvs[:labels] ||= [kvs[:label]] if kvs.has_key? :label
64
+
65
+ # Don't use ||= here, because we need to tell `false` from `nil`
66
+ kvs[:size] = [600, 450] unless kvs.has_key? :size
67
+ kvs[:ax] = false unless kvs.has_key? :ax
68
+ kvs[:subplot] = [0, 1, 0, 1] unless kvs.has_key? :subplot
69
+ kvs[:clear] = true unless kvs.has_key? :clear
70
+ kvs[:update] = true unless kvs.has_key? :update
71
+
72
+ @scheme = 0
72
73
  @background = 0xffffff
73
- @handle = nil
74
+ # @handle = nil # This variable will be used in gr_meta
75
+
74
76
  self.class.last_plot = self
75
77
  end
76
- attr_accessor :args, :kvs, :scheme
77
78
 
78
79
  def set_viewport(kind, subplot)
79
80
  mwidth, mheight, width, height = GR.inqdspsize
80
- if kvs[:figsize]
81
- w = 0.0254 * width * kvs[:figsize][0] / mwidth
82
- h = 0.0254 * height * kvs[:figsize][1] / mheight
83
- else
84
- dpi = width / mwidth * 0.0254
85
- if dpi > 200
86
- w, h = kvs[:size].map { |x| x * dpi / 100 }
87
- else
88
- w, h = kvs[:size]
89
- end
90
- end
91
- viewport = [0, 0, 0, 0]
81
+ dpi = width / mwidth * 0.0254
82
+ w, h = if kvs[:figsize]
83
+ [(0.0254 * width * kvs[:figsize][0] / mwidth),
84
+ (0.0254 * height * kvs[:figsize][1] / mheight)]
85
+ elsif dpi > 200
86
+ kvs[:size].map { |i| i * dpi / 100 }
87
+ else
88
+ kvs[:size]
89
+ end
90
+
92
91
  vp = subplot.clone
92
+
93
93
  if w > h
94
94
  ratio = h / w.to_f
95
95
  msize = mwidth * w / width
@@ -105,6 +105,7 @@ module GR
105
105
  vp[0] *= ratio
106
106
  vp[1] *= ratio
107
107
  end
108
+
108
109
  if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
109
110
  extent = [vp[1] - vp[0], vp[3] - vp[2]].min
110
111
  vp1 = 0.5 * (vp[0] + vp[1] - extent)
@@ -114,10 +115,12 @@ module GR
114
115
  else
115
116
  vp1, vp2, vp3, vp4 = vp
116
117
  end
117
- viewport[0] = vp1 + 0.125 * (vp2 - vp1)
118
- viewport[1] = vp1 + 0.925 * (vp2 - vp1)
119
- viewport[2] = vp3 + 0.125 * (vp4 - vp3)
120
- viewport[3] = vp3 + 0.925 * (vp4 - vp3)
118
+
119
+ viewport = [vp1 + 0.125 * (vp2 - vp1),
120
+ vp1 + 0.925 * (vp2 - vp1),
121
+ vp3 + 0.125 * (vp4 - vp3),
122
+ vp3 + 0.925 * (vp4 - vp3)]
123
+
121
124
  if %i[contour contourf hexbin heatmap nonuniformheatmap polarheatmap
122
125
  surface trisurf volume].include?(kind)
123
126
  viewport[1] -= 0.1
@@ -131,11 +134,11 @@ module GR
131
134
  end
132
135
  end
133
136
 
134
- GR.setviewport(viewport[0], viewport[1], viewport[2], viewport[3])
137
+ GR.setviewport(*viewport)
135
138
 
136
139
  kvs[:viewport] = viewport
137
- kvs[:vp] = vp
138
- kvs[:ratio] = ratio
140
+ kvs[:vp] = vp
141
+ kvs[:ratio] = ratio
139
142
 
140
143
  if kvs[:backgroundcolor]
141
144
  GR.savestate
@@ -165,14 +168,15 @@ module GR
165
168
  def set_window(kind)
166
169
  scale = 0
167
170
  unless %i[polar polarhist polarheatmap].include?(kind)
168
- scale |= GR::OPTION_X_LOG if kvs[:xlog]
169
- scale |= GR::OPTION_Y_LOG if kvs[:ylog]
170
- scale |= GR::OPTION_Z_LOG if kvs[:zlog]
171
+ scale |= GR::OPTION_X_LOG if kvs[:xlog]
172
+ scale |= GR::OPTION_Y_LOG if kvs[:ylog]
173
+ scale |= GR::OPTION_Z_LOG if kvs[:zlog]
171
174
  scale |= GR::OPTION_FLIP_X if kvs[:xflip]
172
175
  scale |= GR::OPTION_FLIP_Y if kvs[:yflip]
173
176
  scale |= GR::OPTION_FLIP_Z if kvs[:zflip]
174
177
  end
175
178
  kvs[:scale] = scale
179
+
176
180
  if kvs.has_key?(:panzoom)
177
181
  xmin, xmax, ymin, ymax = GR.panzoom(*kvs[:panzoom])
178
182
  kvs[:xrange] = [xmin, xmax]
@@ -188,65 +192,74 @@ module GR
188
192
  5
189
193
  end
190
194
 
195
+ kvs[:xticks] = [kvs[:xticks], major_count] if kvs[:xticks].is_a? Numeric
196
+ kvs[:yticks] = [kvs[:yticks], major_count] if kvs[:yticks].is_a? Numeric
197
+ kvs[:zticks] = [kvs[:zticks], major_count] if kvs[:zticks].is_a? Numeric
198
+
191
199
  xmin, xmax = kvs[:xrange]
192
- if (scale & GR::OPTION_X_LOG) == 0
193
- xmin, xmax = GR.adjustlimits(xmin, xmax) unless kvs.has_key?(:xlim) || kvs.has_key?(:panzoom)
194
- if kvs.has_key?(:xticks)
195
- xtick, majorx = kvs[:xticks]
196
- else
197
- majorx = major_count
198
- xtick = GR.tick(xmin, xmax) / majorx
199
- end
200
- else
201
- xtick = majorx = 1
200
+ if %i[heatmap polarheatmap].include?(kind) && kvs.has_key?(:xlim)
201
+ xmin -= 0.5
202
+ xmax += 0.5
202
203
  end
203
- xorg = if (scale & GR::OPTION_FLIP_X) == 0
204
- [xmin, xmax]
205
- else
206
- [xmax, xmin]
207
- end
204
+ xtick, majorx = if (scale & GR::OPTION_X_LOG) == 0
205
+ unless %i[heatmap polarheatmap].include?(kind)
206
+ unless kvs.has_key?(:xlim)
207
+ xmin, xmax = GR.adjustlimits(xmin, xmax) unless kvs[:panzoom]
208
+ end
209
+ end
210
+ if kvs.has_key?(:xticks)
211
+ kvs[:xticks]
212
+ else
213
+ [GR.tick(xmin, xmax) / major_count, major_count]
214
+ end
215
+ else
216
+ [1, 1]
217
+ end
218
+ xorg = (scale & GR::OPTION_FLIP_X) == 0 ? [xmin, xmax] : [xmax, xmin]
208
219
  kvs[:xaxis] = xtick, xorg, majorx
209
220
 
210
221
  ymin, ymax = kvs[:yrange]
211
- if kind == :hist && !kvs.has_key?(:ylim)
212
- ymin = (scale & GR::OPTION_Y_LOG) == 0 ? 0 : 1
222
+ if %i[heatmap polarheatmap].include?(kind) && kvs.has_key?(:ylim)
223
+ ymin -= 0.5
224
+ ymax += 0.5
213
225
  end
214
- if (scale & GR::OPTION_Y_LOG) == 0
215
- ymin, ymax = GR.adjustlimits(ymin, ymax) unless kvs.has_key?(:ylim) || kvs.has_key?(:panzoom)
216
- if kvs.has_key?(:yticks)
217
- ytick, majory = kvs[:yticks]
218
- else
219
- majory = major_count
220
- ytick = GR.tick(ymin, ymax) / majory
226
+ if kind == :hist
227
+ if kvs[:horizontal] && !kvs.has_key?(:xlim)
228
+ xmin = (scale & GR::OPTION_X_LOG) == 0 ? 0 : 1
229
+ elsif !kvs.has_key?(:ylim)
230
+ ymin = (scale & GR::OPTION_Y_LOG) == 0 ? 0 : 1
221
231
  end
222
- else
223
- ytick = majory = 1
224
232
  end
225
- yorg = if (scale & GR::OPTION_FLIP_Y) == 0
226
- [ymin, ymax]
227
- else
228
- [ymax, ymin]
229
- end
233
+ ytick, majory = if (scale & GR::OPTION_Y_LOG) == 0
234
+ unless %i[heatmap polarheatmap].include?(kind)
235
+ unless kvs.has_key?(:ylim)
236
+ ymin, ymax = GR.adjustlimits(ymin, ymax) unless kvs[:panzoom]
237
+ end
238
+ end
239
+ if kvs.has_key?(:yticks)
240
+ kvs[:yticks]
241
+ else
242
+ [GR.tick(ymin, ymax) / major_count, major_count]
243
+ end
244
+ else
245
+ [1, 1]
246
+ end
247
+ yorg = (scale & GR::OPTION_FLIP_Y) == 0 ? [ymin, ymax] : [ymax, ymin]
230
248
  kvs[:yaxis] = ytick, yorg, majory
231
249
 
232
250
  if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
233
251
  zmin, zmax = kvs[:zrange]
234
- if (scale & GR::OPTION_Z_LOG) == 0
235
- zmin, zmax = GR.adjustlimits(zmin, zmax) if kvs.has_key?(:zlim)
236
- if kvs.has_key?(:zticks)
237
- ztick, majorz = kvs[:zticks]
238
- else
239
- majorz = major_count
240
- ztick = GR.tick(zmin, zmax) / majorz
241
- end
242
- else
243
- ztick = majorz = 1
244
- end
245
- zorg = if (scale & GR::OPTION_FLIP_Z) == 0
246
- [zmin, zmax]
247
- else
248
- [zmax, zmin]
249
- end
252
+ ztick, majorz = if (scale & GR::OPTION_Z_LOG) == 0
253
+ zmin, zmax = GR.adjustlimits(zmin, zmax) if kvs.has_key?(:zlim)
254
+ if kvs.has_key?(:zticks)
255
+ kvs[:zticks]
256
+ else
257
+ [GR.tick(zmin, zmax) / major_count, major_count]
258
+ end
259
+ else
260
+ [1, 1]
261
+ end
262
+ zorg = (scale & GR::OPTION_FLIP_Z) == 0 ? [zmin, zmax] : [zmax, zmin]
250
263
  kvs[:zaxis] = ztick, zorg, majorz
251
264
  end
252
265
 
@@ -258,7 +271,7 @@ module GR
258
271
  end
259
272
  if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
260
273
  rotation = kvs[:rotation] || 40
261
- tilt = kvs[:tilt] || 70
274
+ tilt = kvs[:tilt] || 70
262
275
  GR.setspace(zmin, zmax, rotation, tilt)
263
276
  end
264
277
 
@@ -272,7 +285,7 @@ module GR
272
285
  ratio = kvs[:ratio]
273
286
  xtick, xorg, majorx = kvs[:xaxis]
274
287
  ytick, yorg, majory = kvs[:yaxis]
275
- drawgrid = kvs[:grid] || true
288
+ drawgrid = kvs.has_key?(:grid) ? kvs[:grid] : true
276
289
  xtick = 10 if kvs[:scale] & GR::OPTION_X_LOG != 0
277
290
  ytick = 10 if kvs[:scale] & GR::OPTION_Y_LOG != 0
278
291
  GR.setlinecolorind(1)
@@ -293,8 +306,8 @@ module GR
293
306
  else
294
307
  if %i[heatmap nonuniformheatmap shade].include?(kind)
295
308
  ticksize = -ticksize
296
- else
297
- drawgrid && GR.grid(xtick, ytick, 0, 0, majorx, majory)
309
+ elsif drawgrid
310
+ GR.grid(xtick, ytick, 0, 0, majorx, majory)
298
311
  end
299
312
  if kvs.has_key?(:xticklabels) || kvs.has_key?(:yticklabels)
300
313
  fx = if kvs.has_key?(:xticklabels)
@@ -332,7 +345,7 @@ module GR
332
345
  GR.axes(xtick, ytick, xorg[1], yorg[1], -majorx, -majory, -ticksize)
333
346
  end
334
347
 
335
- if kvs.has_key?(:title)
348
+ if kvs[:title]
336
349
  GR.savestate
337
350
  GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_TOP)
338
351
  text(0.5 * (viewport[0] + viewport[1]), vp[3], kvs[:title])
@@ -421,7 +434,7 @@ module GR
421
434
  if img.is_a? String
422
435
  width, height, data = GR.readimage(img)
423
436
  else
424
- width, height = img.shape
437
+ height, width = img.shape
425
438
  cmin, cmax = kvs[:crange]
426
439
  data = img.map { |i| normalize_color(i, cmin, cmax) }
427
440
  data = data.map { |i| (1000 + i * 255).round }
@@ -488,7 +501,9 @@ module GR
488
501
  end
489
502
 
490
503
  GR.selntran(0)
491
- values = ((v - v.min) / (v.max - v.min) * (2 ^ 16 - 1)).round
504
+ v = Numo::DFloat.cast(v) if v.is_a? Array
505
+ values = ((v - v.min) / (v.max - v.min) * (2**16 - 1)).round
506
+ values = Numo::UInt16.cast(values)
492
507
  nx, ny, nz = v.shape
493
508
  isovalue = ((kvs[:isovalue] || 0.5) - v.min) / (v.max - v.min)
494
509
  rotation = ((kvs[:rotation] || 40) * Math::PI / 180.0)
@@ -497,7 +512,7 @@ module GR
497
512
  GR3.clear
498
513
  mesh = GR3.createisosurfacemesh(values, [2.0 / (nx - 1), 2.0 / (ny - 1), 2.0 / (nz - 1)],
499
514
  [-1, -1, -1],
500
- (isovalue * (2 ^ 16 - 1)).round)
515
+ (isovalue * (2**16 - 1)).round)
501
516
  color = kvs[:color] || [0.0, 0.5, 0.8]
502
517
  GR3.setbackgroundcolor(1, 1, 1, 0)
503
518
  GR3.drawmesh(mesh, 1, [0, 0, 0], [0, 0, 1], [0, 1, 0], color, [1, 1, 1])
@@ -562,7 +577,9 @@ module GR
562
577
  # Not yet.
563
578
  end
564
579
 
565
- GR.settextfontprec(232, 3)
580
+ # The following fonts are the default in GR.jl
581
+ # Japanese, Chinese, Korean, etc. cannot be displayed.
582
+ # GR.settextfontprec(232, 3) # CM Serif Roman
566
583
 
567
584
  set_viewport(kind, kvs[:subplot])
568
585
  unless kvs[:ax]
@@ -630,8 +647,7 @@ module GR
630
647
  if z || c
631
648
  if c
632
649
  cmin, cmax = kvs[:crange]
633
- c = c.to_a if narray?(c)
634
- c.map! { |i| normalize_color(i, cmin, cmax) }
650
+ c = c.map { |i| normalize_color(i, cmin, cmax) }
635
651
  cind = c.map { |i| (1000 + i * 255).round }
636
652
  end
637
653
  x.length.times do |i|
@@ -656,14 +672,26 @@ module GR
656
672
  GR.polymarker(x, y)
657
673
 
658
674
  when :hist
659
- ymin = kvs[:window][2]
660
- y.length.times do |i|
661
- GR.setfillcolorind(989)
662
- GR.setfillintstyle(GR::INTSTYLE_SOLID)
663
- GR.fillrect(x[i], x[i + 1], ymin, y[i])
664
- GR.setfillcolorind(1)
665
- GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
666
- GR.fillrect(x[i], x[i + 1], ymin, y[i])
675
+ if kvs[:horizontal]
676
+ xmin = kvs[:window][0]
677
+ x.length.times do |i|
678
+ GR.setfillcolorind(989)
679
+ GR.setfillintstyle(GR::INTSTYLE_SOLID)
680
+ GR.fillrect(xmin, x[i], y[i], y[i + 1])
681
+ GR.setfillcolorind(1)
682
+ GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
683
+ GR.fillrect(xmin, x[i], y[i], y[i + 1])
684
+ end
685
+ else
686
+ ymin = kvs[:window][2]
687
+ y.length.times do |i|
688
+ GR.setfillcolorind(989)
689
+ GR.setfillintstyle(GR::INTSTYLE_SOLID)
690
+ GR.fillrect(x[i], x[i + 1], ymin, y[i])
691
+ GR.setfillcolorind(1)
692
+ GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
693
+ GR.fillrect(x[i], x[i + 1], ymin, y[i])
694
+ end
667
695
  end
668
696
 
669
697
  when :polarhist
@@ -684,9 +712,10 @@ module GR
684
712
  cmap = colormap
685
713
  cmin, cmax = kvs[:zrange]
686
714
  data = z.map { |i| normalize_color(i, cmin, cmax) }
687
- colors = data.map { |i| 1000 + i * 255 }
688
- # if kvs[:xflip]
689
- # if kvs[;yflip]
715
+ data.reverse(axis: 0) if kvs[:xflip]
716
+ data.reverse(axis: 1) if kvs[:yflip]
717
+ colors = data * 255 + 1000
718
+ colors = colors.transpose # Julia is column major
690
719
  GR.polarcellarray(0, 0, 0, 360, 0, 1, w, h, colors)
691
720
  draw_polar_axes
692
721
  kvs[:zrange] = [cmin, cmax]
@@ -698,11 +727,18 @@ module GR
698
727
  a, b = z.shape
699
728
  x = (1..b).to_a
700
729
  y = (1..a).to_a
701
- zmin, zmax = kvs[:zlim] || z.minmax
730
+ zmin, zmax = z.minmax
702
731
  elsif equal_length(x, y, z)
703
732
  x, y, z = GR.gridit(x, y, z, 200, 200)
704
- zmin, zmax = kvs[:zlim] || z.compact.minmax # compact : removed nil
733
+ zmin, zmax = z.compact.minmax # compact : removed nil
734
+ end
735
+
736
+ # kvs[:zlim] is supposed to be Array or Range
737
+ if kvs.has_key?(:zlim)
738
+ zmin = kvs[:zlim].first if kvs[:zlim].first
739
+ zmax = kvs[:zlim].last if kvs[:zlim].last
705
740
  end
741
+
706
742
  GR.setspace(zmin, zmax, 0, 90)
707
743
  levels = kvs[:levels] || 0
708
744
  clabels = kvs[:clabels] || false
@@ -803,7 +839,7 @@ module GR
803
839
  GR.setmarkertype(GR::MARKERTYPE_SOLID_CIRCLE)
804
840
  if c
805
841
  cmin, cmax = kvs[:crange]
806
- c = c.map { |i| normalize_color(i, cmin, cmax) } # NArray -> Array
842
+ c = c.map { |i| normalize_color(i, cmin, cmax) }
807
843
  cind = c.map { |i| (1000 + i * 255).round }
808
844
  x.length.times do |i|
809
845
  GR.setmarkercolorind(cind[i])
@@ -1009,7 +1045,9 @@ module GR
1009
1045
 
1010
1046
  # Normalize a color c with the range [cmin, cmax]
1011
1047
  # 0 <= normalize_color(c, cmin, cmax) <= 1
1048
+ # Note: narray.map{|i| normalize_color(i)} There's room for speedup.
1012
1049
  def normalize_color(c, cmin, cmax)
1050
+ c = c.to_f # if c is Integer
1013
1051
  c = c.clamp(cmin, cmax) - cmin
1014
1052
  c /= (cmax - cmin) if cmin != cmax
1015
1053
  c
@@ -1050,7 +1088,8 @@ module GR
1050
1088
  args.each do |x, y, z, c|
1051
1089
  if x
1052
1090
  if scale & GR::OPTION_X_LOG != 0
1053
- x.map! { |v| v > 0 ? v : Float::NAN }
1091
+ # duck typing for NArray
1092
+ x = x.map { |v| v > 0 ? v : Float::NAN }
1054
1093
  end
1055
1094
  x0, x1 = x.minmax
1056
1095
  xmin = [x0, xmin].min
@@ -1061,7 +1100,7 @@ module GR
1061
1100
  end
1062
1101
  if y
1063
1102
  if scale & GR::OPTION_Y_LOG != 0
1064
- y.map! { |v| v > 0 ? v : Float::NAN }
1103
+ y = y.map { |v| v > 0 ? v : Float::NAN }
1065
1104
  end
1066
1105
  y0, y1 = y.minmax
1067
1106
  ymin = [y0, ymin].min
@@ -1072,7 +1111,7 @@ module GR
1072
1111
  end
1073
1112
  if z
1074
1113
  if scale & GR::OPTION_Z_LOG != 0
1075
- z.map! { |v| v > 0 ? v : Float::NAN }
1114
+ z = z.map { |v| v > 0 ? v : Float::NAN }
1076
1115
  end
1077
1116
  z0, z1 = z.minmax
1078
1117
  zmin = [z0, zmin].min
@@ -1091,30 +1130,12 @@ module GR
1091
1130
  xmin, xmax = fix_minmax(xmin, xmax)
1092
1131
  ymin, ymax = fix_minmax(ymin, ymax)
1093
1132
  zmin, zmax = fix_minmax(zmin, zmax)
1094
- if kvs.has_key?(:xlim)
1095
- x0, x1 = kvs[:xlim]
1096
- x0 ||= xmin
1097
- x1 ||= xmax
1098
- kvs[:xrange] = [x0, x1]
1099
- else
1100
- kvs[:xrange] = [xmin, xmax]
1101
- end
1102
- if kvs.has_key?(:ylim)
1103
- y0, y1 = kvs[:ylim]
1104
- y0 ||= ymin
1105
- y1 ||= ymax
1106
- kvs[:yrange] = [y0, y1]
1107
- else
1108
- kvs[:yrange] = [ymin, ymax]
1109
- end
1110
- if kvs.has_key?(:zlim)
1111
- z0, z1 = kvs[:zlim]
1112
- z0 ||= zmin
1113
- z1 ||= zmax
1114
- kvs[:zrange] = [z0, z1]
1115
- else
1116
- kvs[:zrange] = [zmin, zmax]
1117
- end
1133
+
1134
+ # kvs[:xlim], kvs[:ylim], kvs[:zlim] is supposed to be Array or Range
1135
+ kvs[:xrange] = [(kvs[:xlim]&.first || xmin), (kvs[:xlim]&.last || xmax)]
1136
+ kvs[:yrange] = [(kvs[:ylim]&.first || ymin), (kvs[:ylim]&.last || ymax)]
1137
+ kvs[:zrange] = [(kvs[:zlim]&.first || zmin), (kvs[:zlim]&.last || zmax)]
1138
+
1118
1139
  if kvs.has_key?(:clim)
1119
1140
  c0, c1 = kvs[:clim]
1120
1141
  c0 ||= cmin
@@ -1290,9 +1311,8 @@ module GR
1290
1311
  def barplot(labels, heights, kv = {})
1291
1312
  labels = labels.map(&:to_s)
1292
1313
  wc, hc = barcoordinates(heights)
1293
- horizontal = kv[:horizontal] || false
1294
1314
  create_plot(:bar, labels, heights, kv) do |plt|
1295
- if horizontal
1315
+ if kv[:horizontal]
1296
1316
  plt.args = [[hc, wc, nil, nil, '']]
1297
1317
  plt.kvs[:yticks] = [1, 1]
1298
1318
  plt.kvs[:yticklabels] = labels
@@ -1305,11 +1325,15 @@ module GR
1305
1325
  end
1306
1326
 
1307
1327
  # (Plot) Draw a histogram.
1308
- def histogram(x, kv = {})
1309
- create_plot(:hist, x, kv) do |plt|
1328
+ def histogram(series, kv = {})
1329
+ create_plot(:hist, series, kv) do |plt|
1310
1330
  nbins = plt.kvs[:nbins] || 0
1311
- x, y = hist(x, nbins)
1312
- plt.args = [[x, y, nil, nil, '']]
1331
+ x, y = hist(series, nbins)
1332
+ plt.args = if kv[:horizontal]
1333
+ [[y, x, nil, nil, '']]
1334
+ else
1335
+ [[x, y, nil, nil, '']]
1336
+ end
1313
1337
  end
1314
1338
  end
1315
1339
 
@@ -1335,7 +1359,7 @@ module GR
1335
1359
  end
1336
1360
 
1337
1361
  # Set current subplot index.
1338
- def subplot(nr, nc, p)
1362
+ def subplot(nr, nc, p, kv = {})
1339
1363
  xmin = 1
1340
1364
  xmax = 0
1341
1365
  ymin = 1
@@ -1351,9 +1375,10 @@ module GR
1351
1375
  end
1352
1376
  {
1353
1377
  subplot: [xmin, xmax, ymin, ymax],
1378
+ # The policy of clearing when p[0]==1 is controversial
1354
1379
  clear: p[0] == 1,
1355
1380
  update: p[-1] == nr * nc
1356
- }
1381
+ }.merge kv
1357
1382
  end
1358
1383
 
1359
1384
  # (Plot) Save the current figure to a file.