ruby-gr 0.0.17 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 668fdb6db9526bf6b55fb6b293aa776ec625b76a650be20852efcd2869f1c751
4
- data.tar.gz: 3b3a7645021470b12840734506f2a466d32fdff111c0e7dd6762ccf9e374ee92
3
+ metadata.gz: d61176c3d03c6d635adbdc0cec5dd701b2303862405fa63a60815fc03b724054
4
+ data.tar.gz: 405d76e691b88c53d471b2e552f1af310e0a4d4b377c02ecbeac1827e62f5921
5
5
  SHA512:
6
- metadata.gz: 982637afaeb9be0f9b7abb631e1554fd04a2082ec7b019cb55e4f8d4ec870634f734b1b28dda8177e784a593476e0f065a924bd362ba58a881210015a7ec2f4c
7
- data.tar.gz: 5bd9205778607854747d7ab9e4c1165600792710a9c3df0452c3c306fceff7ab90d665ccb244aa4761c407f59df9c3f80413bf4663ff81643887966b87109e27
6
+ metadata.gz: 4d23ae259c265dd3e8ed030a31a7f04ca4e358859e807885cda9f53c2c4b0be5839ccb2464bd4a6c2c9cf5d68fd99665d3f32dd74254ddd2eadfe4fe7123e9e3
7
+ data.tar.gz: 20b3a2dfec804617038a5884e272197d92f6f10069e568b149736d63775054d4d0c29e6f346397338401db44da1a4f3d9d5ba3c3f65a461c38df97ed8d10dc34
data/README.md CHANGED
@@ -6,31 +6,43 @@
6
6
  [![Gitter Chat](https://badges.gitter.im/red-data-tools/en.svg)](https://gitter.im/red-data-tools/en)
7
7
  [![Docs Latest](https://img.shields.io/badge/docs-latest-blue.svg)](https://rubydoc.info/gems/ruby-gr)
8
8
 
9
- <p align="center">
10
- <img src="https://user-images.githubusercontent.com/5798442/70857099-13d57600-1f2c-11ea-8f3c-7d81065f13a5.png">
11
- </p>
12
-
13
- :bar_chart: [GR framework](https://github.com/sciapp/gr) - the graphics library for visualization - for Ruby
9
+ [![rdatasets-1](https://i.imgur.com/XEQ6wKs.png)](examples/rdatasets.rb)
10
+ [![stem](https://i.imgur.com/3w0Ejrm.png)](examples/fast_plots.rb)
11
+ [![histogram](https://i.imgur.com/xUdoA2s.png)](examples/fast_plots.rb)
12
+ [![barplot](https://i.imgur.com/52bOFKE.png)](examples/fast_plots.rb)
13
+ [![scatter3](https://i.imgur.com/yTTVetQ.png)](examples/fast_plots.rb)
14
+ [![volume](https://i.imgur.com/CuRN6oC.png)](examples/fast_plots.rb)
15
+ [![griddata](https://i.imgur.com/58HdYDo.png)](examples/griddata.rb)
16
+ [![2darray](https://i.imgur.com/aKR2FJG.png)](examples/2darray.rb)
17
+ [![2dpolararray](https://i.imgur.com/cmSrxvS.png)](examples/2dpolararray.rb)
18
+ [![hexbin](https://i.imgur.com/unWhQHr.png)](examples/hexbin.rb)
19
+ [![rdatasets-2](https://i.imgur.com/ZPit2F5.png)](examples/rdatasets.rb)
20
+ [![rdatasets-3](https://i.imgur.com/TbNoxwy.png)](examples/rdatasets.rb)
21
+ [![surface](https://i.imgur.com/sWdaHme.png)](examples/kws2.rb)
22
+ [![face](https://i.imgur.com/uLCKi2r.png)](examples/face.rb)
23
+ [![shade](https://i.imgur.com/VJmS3EQ.png)](examples/shade_ex.rb)
24
+
25
+ :bar_chart: [GR framework](https://github.com/sciapp/gr) - powerful visualization library - for Ruby
14
26
 
15
27
  ## Installation
16
28
 
17
- GR.rb supports Ruby 2.4+.
18
-
19
- [Install GR](#gr-installation).
29
+ GR.rb supports Ruby 2.5+.
20
30
 
21
- Set environment variable GRDIR, if you have not already done.
31
+ First, [install GR](#gr-installation). Then install `ruby-gr` gem.
22
32
 
23
33
  ```sh
24
- export GRDIR="/your/path/to/gr"
34
+ gem install ruby-gr
25
35
  ```
26
36
 
27
- Add this line to your application's Gemfile:
37
+ Note: If you are using Rubyinstaller(Windows), pacman will automatically install [mingw-w64-gr](https://packages.msys2.org/base/mingw-w64-gr).
38
+
39
+ Set environment variable `GRDIR`.
28
40
 
29
41
  ```sh
30
- gem 'ruby-gr'
42
+ export GRDIR="/your/path/to/gr"
31
43
  ```
32
44
 
33
- GR3 and GR::Plot require [numo-narray](https://github.com/ruby-numo/numo-narray).
45
+ Note: If you use package managers to install GR, [pkg-config](https://github.com/ruby-gnome/pkg-config) may automatically detect the shared library location without specifying the `GRDIR` environment variable.
34
46
 
35
47
  ## Quick Start
36
48
 
@@ -47,43 +59,103 @@ y = [0.3, 0.5, 0.4, 0.2, 0.6, 0.7]
47
59
  GR.plot(x, y)
48
60
  ```
49
61
 
50
- ## Examples
62
+ <p align="center">
63
+ <img src="https://user-images.githubusercontent.com/5798442/84570709-242ab880-adca-11ea-9099-3a6b3418bf19.png">
64
+ </p>
65
+
66
+ ```ruby
67
+ require 'gr/plot'
68
+
69
+ x = Numo::DFloat.linspace(0, 10, 101)
70
+ y1 = Numo::NMath.sin(x)
71
+ y2 = Numo::NMath.cos(x)
72
+
73
+ GR.plot(
74
+ [x, y1, 'bo'], [x, y2, 'g*'],
75
+ title: "Multiple plot example",
76
+ xlabel: "x",
77
+ ylabel: "y",
78
+ ylim: [-1.2, 1.2],
79
+ labels: ["sin(x)", "cos(x)"],
80
+ location: 11
81
+ )
82
+ ```
83
+
84
+ Save in PNG format.
51
85
 
52
- Have a look in the [`examples`](https://github.com/red-data-tools/GR.rb/tree/master/examples) directory.
53
- * [Example Gallery](https://github.com/red-data-tools/GR.rb/wiki/Example-gallery)
86
+ ```ruby
87
+ GR.savefig("figure.png")
88
+ ```
54
89
 
55
- ## Features
90
+ ## API Overview
56
91
 
57
- #### GR::Plot
92
+ There are two different approaches to plotting with GR.rb. One way is to call Matlab-like APIs. The other is to call GR/GR3 native functions. We are planning to prepare a [more object-oriented interface](https://github.com/kojix2/GRUtils.rb) based on [GRUtils.jl](https://github.com/heliosdrm/GRUtils.jl) in the future.
58
93
 
59
- A simple, matlab-style API.
94
+ #### GR::Plot - A simple, matlab-style API.
60
95
 
61
96
  ```ruby
62
97
  require 'gr/plot'
98
+ GR.plot(x, y)
63
99
  ```
64
100
 
65
- `plot` `step` `scatter` `stem` `histogram` `contour` `contourf` `hexbin` `heatmap` `wireframe` `surface` `plot3` `scatter3` `imshow` `isosurface` `polar` `polarhist` `polarheatmap` `trisurf` `tricont` `shade` `volume`
66
-
67
- #### GR
101
+ List of vailable functions. See [GR.rb Wiki](https://github.com/red-data-tools/GR.rb/wiki) for details.
102
+
103
+ [`plot`](../../wiki/Plotting-functions#plot)
104
+ [`step`](../../wiki/Plotting-functions#step)
105
+ [`plot3`](../../wiki/Plotting-functions#plot3)
106
+ [`polar`](../../wiki/Plotting-functions#polar)
107
+ [`scatter`](../../wiki/Plotting-functions#scatter)
108
+ [`scatter3`](../../wiki/Plotting-functions#scatter3)
109
+ [`stem`](../../wiki/Plotting-functions#stem)
110
+ [`barplot`](../../wiki/Plotting-functions#barplot)
111
+ [`histogram`](../../wiki/Plotting-functions#histogram)
112
+ [`polarhistogram`](../../wiki/Plotting-functions#polarhistogram)
113
+ [`hexbin`](../../wiki/Plotting-functions#hexbin)
114
+ [`contour`](../../wiki/Plotting-functions#contour)
115
+ [`contourf`](../../wiki/Plotting-functions#contourf)
116
+ [`tricont`](../../wiki/Plotting-functions#tricont)
117
+ [`surface`](../../wiki/Plotting-functions#surface)
118
+ [`trisurf`](../../wiki/Plotting-functions#trisurf)
119
+ [`wireframe`](../../wiki/Plotting-functions#wireframe)
120
+ [`volume`](../../wiki/Plotting-functions#volume)
121
+ [`heatmap`](../../wiki/Plotting-functions#heatmap)
122
+ [`polarheatmap`](../../wiki/Plotting-functions#polarheatmap)
123
+ [`shade`](../../wiki/Plotting-functions#shade)
124
+ [`imshow`](../../wiki/Plotting-functions#imshow)
125
+ [`isosurface`](../../wiki/Plotting-functions#isosurface)
126
+
127
+ #### GR - A module for calling native GR functions.
128
+
129
+ 2-D Plots and common 3-D Plots.
68
130
 
69
131
  ```ruby
70
132
  require 'gr'
133
+
134
+ # For example
135
+ GR.setviewport(0.1, 0.9, 0.1, 0.9)
136
+ GR.setwindow(0.0, 20.0, 0.0, 20.0)
71
137
  ```
72
138
 
73
- #### GR3
139
+ #### GR3 - A module for calling native GR3 functions.
140
+
141
+ Complex 3D scenes.
74
142
 
75
143
  ```ruby
76
144
  require 'gr3'
145
+
146
+ # For example
147
+ GR3.cameralookat(-3, 2, -2, 0, 0, 0, 0, 0, -1)
77
148
  ```
78
149
 
79
150
  ## Documentation
80
151
 
152
+ - [GR.rb Wiki](https://github.com/red-data-tools/GR.rb/wiki)
81
153
  - [GR Framework](https://gr-framework.org/)
82
154
  - [GR.rb API Documentation](https://rubydoc.info/gems/ruby-gr)
83
155
 
84
156
  ## GR Installation
85
157
 
86
- ### Official binary release
158
+ ### Installing an official release (recommended)
87
159
 
88
160
  Download the [latest release](https://github.com/sciapp/gr/releases).
89
161
 
@@ -95,23 +167,25 @@ export GRDIR="your/path/to/gr"
95
167
 
96
168
  * macOS Catalina and macOS Mojave: See the "How to open an app that hasn’t been notarized or is from an unidentified developer" section of [Safely open apps on your Mac](https://support.apple.com/en-us/HT202491) in the Apple documentation.
97
169
 
98
- ### Homebrew
170
+ ### Using package managers
99
171
 
100
- ```sh
101
- brew install libgr
102
- ```
172
+ * The third party GR packages for Mac, Linux and Windows are available (for advanced users).
173
+ * If you find any problem, please report the issue [here](https://github.com/red-data-tools/GR.rb/issues).
174
+ * Note: These packages may not have some features, for example, video output.
103
175
 
104
- Set environment variable GRDIR.
176
+ #### Mac - Homebrew
105
177
 
106
178
  ```sh
107
- export GRDIR=$(brew --prefix libgr)
179
+ brew install libgr
108
180
  ```
109
181
 
110
- If you fail to build libgr using homebrew, Please feel free to [send us your feedback](https://github.com/red-data-tools/GR.rb/issues).
182
+ #### Linux - APT Yum
183
+
184
+ [packages.red-data-tools.org](https://github.com/red-data-tools/packages.red-data-tools.org) provides `libgr-dev`, `libgr3-dev` and `libgrm-dev`
111
185
 
112
- ### Red data tools repository
186
+ ### Windows - MSYS2
113
187
 
114
- Red data tools provides [packages](https://github.com/red-data-tools/packages.red-data-tools.org ) related to our project including `libgr-dev` and `libgr3-dev` for advanced users.
188
+ If you are using Rubyinstaller, pacman will automatically install [mingw-w64-gr](https://packages.msys2.org/base/mingw-w64-gr) when the gem is installed.
115
189
 
116
190
  ## Backend for Charty
117
191
 
@@ -119,13 +193,14 @@ GR.rb will be the default backend for [Charty](https://github.com/red-data-tools
119
193
 
120
194
  ## Contributing
121
195
 
122
- * Report bugs
123
- * Fix bugs and submit pull requests
196
+ * [Report bugs](https://github.com/red-data-tools/GR.rb/issues)
197
+ * Fix bugs and [submit pull requests](https://github.com/red-data-tools/GR.rb/pulls)
124
198
  * Write, clarify, or fix documentation
125
199
  * Suggest or add new features
126
- * Create visualization library based on GR.rb
200
+ * Update GR packages ( Homebrew, MinGW, red-data-tools )
201
+ * Create visualization tools based on GR.rb
127
202
 
128
203
  ## Acknowledgements
129
204
 
130
- We would like to thank Josef Heinen, the creator of [GR.jl](https://github.com/jheinen/GR.jl), Florian Rhiem, the creator of [python-gr](https://github.com/sciapp/python-gr), and [GR](https://github.com/sciapp/gr) developers.
205
+ We would like to thank Josef Heinen, the creator of [GR](https://github.com/sciapp/gr) and [GR.jl](https://github.com/jheinen/GR.jl), Florian Rhiem, the creator of [python-gr](https://github.com/sciapp/python-gr), and all [GR](https://github.com/sciapp/gr) developers.
131
206
 
data/lib/gr.rb CHANGED
@@ -52,23 +52,20 @@ module GR
52
52
  attr_accessor :ffi_lib
53
53
  end
54
54
 
55
- raise Error, 'Please set env variable GRDIR' unless ENV['GRDIR']
55
+ require_relative 'gr_commons/gr_commons'
56
+ extend GRCommons::SearchSharedLibrary
56
57
 
57
58
  # Platforms | path
58
59
  # Windows | bin/libgr.dll
59
60
  # MacOSX | lib/libGR.so (NOT .dylib)
60
61
  # Ubuntu | lib/libGR.so
61
- if Object.const_defined?(:RubyInstaller)
62
- self.ffi_lib = File.expand_path('bin/libgr.dll', ENV['GRDIR'])
63
- RubyInstaller::Runtime.add_dll_directory(File.dirname(ffi_lib))
64
- else
65
- self.ffi_lib = File.expand_path('lib/libGR.so', ENV['GRDIR'])
66
- end
67
-
68
- # Change the default encoding to UTF-8.
69
- ENV['GKS_ENCODING'] ||= 'utf8'
62
+ self.ffi_lib = case RbConfig::CONFIG['host_os']
63
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
64
+ search_shared_library('libgr.dll', 'gr')
65
+ else
66
+ search_shared_library('libGR.so', 'gr')
67
+ end
70
68
 
71
- require_relative 'gr_commons/gr_commons'
72
69
  require_relative 'gr/version'
73
70
  require_relative 'gr/ffi'
74
71
  require_relative 'gr/grbase'
@@ -99,7 +96,12 @@ module GR
99
96
  super
100
97
  end
101
98
 
102
- # inqdspsize
99
+ # Get the current display size.
100
+ # Depending on the current workstation type, the current display might be
101
+ # the primary screen (e.g. when using gksqt or GKSTerm) or a purely virtual
102
+ # display (e.g. when using Cairo). When a high DPI screen is used as the
103
+ # current display, width and height will be in logical pixels.
104
+ # @return [Array] meter_width, meter_height, width, height
103
105
  def inqdspsize
104
106
  inquiry %i[double double int int] do |*pts|
105
107
  super(*pts)
@@ -111,9 +113,7 @@ module GR
111
113
  # @param connection [String] A connection identifier.
112
114
  # @param workstation_type [Integer] The desired workstation type.
113
115
  # * 5 : Workstation Independent Segment Storage
114
- # * 7, 8 : Computer Graphics Metafile (CGM binary, clear text)
115
116
  # * 41 : Windows GDI
116
- # * 51 : Mac Quickdraw
117
117
  # * 61 - 64 : PostScript (b/w, color)
118
118
  # * 101, 102 : Portable Document Format (plain, compressed)
119
119
  # * 210 - 213 : X Windows
@@ -134,7 +134,6 @@ module GR
134
134
  # * 410 : Socket driver
135
135
  # * 415 : 0MQ driver
136
136
  # * 420 : OpenGL
137
- # * 430 : HTML5 Canvas
138
137
  def openws(*)
139
138
  super
140
139
  end
@@ -157,6 +156,7 @@ module GR
157
156
  super
158
157
  end
159
158
 
159
+ # Configure the specified workstation.
160
160
  def configurews(*)
161
161
  super
162
162
  end
@@ -298,6 +298,7 @@ module GR
298
298
  super(n, x, y, m, method)
299
299
  end
300
300
 
301
+ # Interpolate data from arbitrary points at points on a rectangular grid.
301
302
  def gridit(xd, yd, zd, nx, ny)
302
303
  nd = equal_length(xd, yd, zd)
303
304
  inquiry [{ double: nx }, { double: ny }, { double: nx * ny }] do |px, py, pz|
@@ -359,7 +360,6 @@ module GR
359
360
  super
360
361
  end
361
362
 
362
- # inqlinecolorind
363
363
  def inqlinecolorind
364
364
  inquiry_int { |pt| super(pt) }
365
365
  end
@@ -505,6 +505,8 @@ module GR
505
505
  # * 129 : FONT_PALATINO_BOLDITALIC
506
506
  # * 130 : FONT_ZAPFCHANCERY_MEDIUMITALIC
507
507
  # * 131 : FONT_ZAPFDINGBATS
508
+ # * 232 : FONT_COMPUTERMODERN
509
+ # * 233 : FONT_DEJAVUSANS
508
510
  # @param precision [Integer] Text precision
509
511
  # * 0 : TEXT_PRECISION_STRING
510
512
  # * String precision (higher quality)
@@ -512,10 +514,14 @@ module GR
512
514
  # * Character precision (medium quality)
513
515
  # * 2 : TEXT_PRECISION_STROKE
514
516
  # * Stroke precision (lower quality)
517
+ # * 3 : TEXT_PRECISION_OUTLINE
518
+ # * Outline precision (highest quality)
515
519
  # The appearance of a font depends on the text precision value specified.
516
520
  # STRING, CHARACTER or STROKE precision allows for a greater or lesser
517
521
  # realization of the text primitives, for efficiency. STRING is the default
518
- # precision for GR and produces the highest quality output.
522
+ # precision for GR and produces the highest quality output using either
523
+ # native font rendering or FreeType. OUTLINE uses the GR path rendering
524
+ # functions to draw individual glyphs and produces the highest quality output.
519
525
  def settextfontprec(*)
520
526
  super
521
527
  end
@@ -557,6 +563,14 @@ module GR
557
563
  super
558
564
  end
559
565
 
566
+ # Gets the current character height.
567
+ # This function gets the height of text output primitives. Text height is
568
+ # defined as a percentage of the default window. GR uses the default text
569
+ # height of 0.027 (2.7% of the height of the default window).
570
+ def inqcharheight
571
+ inquiry_double { |pt| super(pt) }
572
+ end
573
+
560
574
  # Set the current character text angle up vector.
561
575
  # @param ux [Numeric] Text up vector
562
576
  # @param uy [Numeric] Text up vector
@@ -618,6 +632,8 @@ module GR
618
632
  # * Fill the interior of the polygon using the style index as a pattern index
619
633
  # * 3 : HATCH
620
634
  # * Fill the interior of the polygon using the style index as a cross-hatched style
635
+ # * 4 : SOLID_WITH_BORDER
636
+ # * Fill the interior of the polygon using the fill color index and draw the bounding polyline
621
637
  # `setfillintstyle` defines the interior style for subsequent fill area output
622
638
  # primitives. The default interior style is HOLLOW.
623
639
  def setfillintstyle(*)
@@ -641,6 +657,7 @@ module GR
641
657
  end
642
658
 
643
659
  # Returns the current fill area color index.
660
+ # This function gets the color index for PATTERN and HATCH fills.
644
661
  def inqfillstyle
645
662
  inquiry_int { |pt| super(pt) }
646
663
  end
@@ -654,6 +671,7 @@ module GR
654
671
  end
655
672
 
656
673
  # Returns the current fill area color index.
674
+ # This function gets the color of fill area output primitives.
657
675
  def inqfillcolorind
658
676
  inquiry_int { |pt| super(pt) }
659
677
  end
@@ -928,12 +946,40 @@ module GR
928
946
  # coordinate unit. Major tick marks are twice as long as minor tick marks.
929
947
  # A negative value reverses the tick marks on the axes from inward facing
930
948
  # to outward facing (or vice versa).
949
+ # Tick marks are positioned along each axis so that major tick marks fall on
950
+ # the axes origin (whether visible or not). Major tick marks are labeled
951
+ # with the corresponding data values. Axes are drawn according to the scale
952
+ # of the window. Axes and tick marks are drawn using solid lines; line color
953
+ # and width can be modified using the gr_setlinetype and gr_setlinewidth
954
+ # functions. Axes are drawn according to the linear or logarithmic
955
+ # transformation established by the gr_setscale function.
931
956
  def axes(*)
932
957
  super
933
958
  end
934
959
 
935
960
  alias axes2d axes
936
961
 
962
+ # Create axes in the current workspace and supply a custom function for
963
+ # changing the behaviour of the tick labels.
964
+ # @param x_tick [Numeric] The interval between minor tick marks on the X axis.
965
+ # @param y_tick [Numeric] The interval between minor tick marks on the Y axis.
966
+ # @param x_org [Numeric] The world coordinate of the origin (point of intersection) of the X axis.
967
+ # @param y_org [Numeric] The world coordinate of the origin (point of intersection) of the Y axis.
968
+ # @param major_x [Integer] Unitless integer value specifying the number of minor tick intervals between major tick marks on the X axis. Values of 0 or 1 imply no minor ticks. Negative values specify no labels will be drawn for the associated axis.
969
+ # @param major_y [Integer] Unitless integer value specifying the number of minor tick intervals between major tick marks on the Y axis. Values of 0 or 1 imply no minor ticks. Negative values specify no labels will be drawn for the associated axis.
970
+ # @param tick_size [Numeric] The length of minor tick marks specified in a normalized device coordinate unit. Major tick marks are twice as long as minor tick marks. A negative value reverses the tick marks on the axes from inward facing to outward facing (or vice versa).
971
+ # @param fpx [Pointer] Function pointer to a function that returns a label for a given tick on the X axis. The callback function should have the following arguments [Numeric]
972
+ # @param fpy [Pointer] Exactly same as the fpx above, but for the the Y axis.
973
+ # Similar to gr_axes() but allows more fine-grained control over tick labels
974
+ # and text positioning by supplying callback functions. Within the callback
975
+ # function you can use normal GR text primitives for performing any
976
+ # manipulations on the label text.
977
+ # See gr_axes() for more details on drawing axes.
978
+ # * fpx/fpy
979
+ # * param x [Numeric] NDC of the label in X direction.
980
+ # * param y [Numeric] NDC of the label in Y direction.
981
+ # * param svalue [String] Internal string representation of the text drawn by GR at (x,y).
982
+ # * param value [Numeric] Floating point representation of the label drawn at (x,y).
937
983
  def axeslbl(*)
938
984
  super
939
985
  end
@@ -1591,10 +1637,10 @@ module GR
1591
1637
  super(npoints, x, y, ntri, triangles.ref)
1592
1638
  end
1593
1639
  if n_tri > 0
1594
- tri = triangles.to_str(3 * n_tri * Fiddle::SIZEOF_INT).unpack('l*') # Int32
1640
+ tri = triangles.to_str(dim * n_tri * Fiddle::SIZEOF_INT).unpack('l*') # Int32
1595
1641
  # Ruby : 0-based indexing
1596
1642
  # Julia : 1-based indexing
1597
- tri = tri.each_slice(3).to_a
1643
+ tri = tri.each_slice(dim).to_a
1598
1644
  [n_tri, tri]
1599
1645
  else
1600
1646
  0
@@ -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])
@@ -564,7 +577,9 @@ module GR
564
577
  # Not yet.
565
578
  end
566
579
 
567
- 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
568
583
 
569
584
  set_viewport(kind, kvs[:subplot])
570
585
  unless kvs[:ax]
@@ -632,8 +647,7 @@ module GR
632
647
  if z || c
633
648
  if c
634
649
  cmin, cmax = kvs[:crange]
635
- c = c.to_a if narray?(c)
636
- c.map! { |i| normalize_color(i, cmin, cmax) }
650
+ c = c.map { |i| normalize_color(i, cmin, cmax) }
637
651
  cind = c.map { |i| (1000 + i * 255).round }
638
652
  end
639
653
  x.length.times do |i|
@@ -658,14 +672,26 @@ module GR
658
672
  GR.polymarker(x, y)
659
673
 
660
674
  when :hist
661
- ymin = kvs[:window][2]
662
- y.length.times do |i|
663
- GR.setfillcolorind(989)
664
- GR.setfillintstyle(GR::INTSTYLE_SOLID)
665
- GR.fillrect(x[i], x[i + 1], ymin, y[i])
666
- GR.setfillcolorind(1)
667
- GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
668
- 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
669
695
  end
670
696
 
671
697
  when :polarhist
@@ -686,9 +712,10 @@ module GR
686
712
  cmap = colormap
687
713
  cmin, cmax = kvs[:zrange]
688
714
  data = z.map { |i| normalize_color(i, cmin, cmax) }
689
- colors = data.map { |i| 1000 + i * 255 }
690
- # if kvs[:xflip]
691
- # 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
692
719
  GR.polarcellarray(0, 0, 0, 360, 0, 1, w, h, colors)
693
720
  draw_polar_axes
694
721
  kvs[:zrange] = [cmin, cmax]
@@ -700,11 +727,18 @@ module GR
700
727
  a, b = z.shape
701
728
  x = (1..b).to_a
702
729
  y = (1..a).to_a
703
- zmin, zmax = kvs[:zlim] || z.minmax
730
+ zmin, zmax = z.minmax
704
731
  elsif equal_length(x, y, z)
705
732
  x, y, z = GR.gridit(x, y, z, 200, 200)
706
- 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
707
740
  end
741
+
708
742
  GR.setspace(zmin, zmax, 0, 90)
709
743
  levels = kvs[:levels] || 0
710
744
  clabels = kvs[:clabels] || false
@@ -805,7 +839,7 @@ module GR
805
839
  GR.setmarkertype(GR::MARKERTYPE_SOLID_CIRCLE)
806
840
  if c
807
841
  cmin, cmax = kvs[:crange]
808
- c = c.map { |i| normalize_color(i, cmin, cmax) } # NArray -> Array
842
+ c = c.map { |i| normalize_color(i, cmin, cmax) }
809
843
  cind = c.map { |i| (1000 + i * 255).round }
810
844
  x.length.times do |i|
811
845
  GR.setmarkercolorind(cind[i])
@@ -1011,7 +1045,9 @@ module GR
1011
1045
 
1012
1046
  # Normalize a color c with the range [cmin, cmax]
1013
1047
  # 0 <= normalize_color(c, cmin, cmax) <= 1
1048
+ # Note: narray.map{|i| normalize_color(i)} There's room for speedup.
1014
1049
  def normalize_color(c, cmin, cmax)
1050
+ c = c.to_f # if c is Integer
1015
1051
  c = c.clamp(cmin, cmax) - cmin
1016
1052
  c /= (cmax - cmin) if cmin != cmax
1017
1053
  c
@@ -1052,7 +1088,8 @@ module GR
1052
1088
  args.each do |x, y, z, c|
1053
1089
  if x
1054
1090
  if scale & GR::OPTION_X_LOG != 0
1055
- x.map! { |v| v > 0 ? v : Float::NAN }
1091
+ # duck typing for NArray
1092
+ x = x.map { |v| v > 0 ? v : Float::NAN }
1056
1093
  end
1057
1094
  x0, x1 = x.minmax
1058
1095
  xmin = [x0, xmin].min
@@ -1063,7 +1100,7 @@ module GR
1063
1100
  end
1064
1101
  if y
1065
1102
  if scale & GR::OPTION_Y_LOG != 0
1066
- y.map! { |v| v > 0 ? v : Float::NAN }
1103
+ y = y.map { |v| v > 0 ? v : Float::NAN }
1067
1104
  end
1068
1105
  y0, y1 = y.minmax
1069
1106
  ymin = [y0, ymin].min
@@ -1074,7 +1111,7 @@ module GR
1074
1111
  end
1075
1112
  if z
1076
1113
  if scale & GR::OPTION_Z_LOG != 0
1077
- z.map! { |v| v > 0 ? v : Float::NAN }
1114
+ z = z.map { |v| v > 0 ? v : Float::NAN }
1078
1115
  end
1079
1116
  z0, z1 = z.minmax
1080
1117
  zmin = [z0, zmin].min
@@ -1093,30 +1130,12 @@ module GR
1093
1130
  xmin, xmax = fix_minmax(xmin, xmax)
1094
1131
  ymin, ymax = fix_minmax(ymin, ymax)
1095
1132
  zmin, zmax = fix_minmax(zmin, zmax)
1096
- if kvs.has_key?(:xlim)
1097
- x0, x1 = kvs[:xlim]
1098
- x0 ||= xmin
1099
- x1 ||= xmax
1100
- kvs[:xrange] = [x0, x1]
1101
- else
1102
- kvs[:xrange] = [xmin, xmax]
1103
- end
1104
- if kvs.has_key?(:ylim)
1105
- y0, y1 = kvs[:ylim]
1106
- y0 ||= ymin
1107
- y1 ||= ymax
1108
- kvs[:yrange] = [y0, y1]
1109
- else
1110
- kvs[:yrange] = [ymin, ymax]
1111
- end
1112
- if kvs.has_key?(:zlim)
1113
- z0, z1 = kvs[:zlim]
1114
- z0 ||= zmin
1115
- z1 ||= zmax
1116
- kvs[:zrange] = [z0, z1]
1117
- else
1118
- kvs[:zrange] = [zmin, zmax]
1119
- 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
+
1120
1139
  if kvs.has_key?(:clim)
1121
1140
  c0, c1 = kvs[:clim]
1122
1141
  c0 ||= cmin
@@ -1292,9 +1311,8 @@ module GR
1292
1311
  def barplot(labels, heights, kv = {})
1293
1312
  labels = labels.map(&:to_s)
1294
1313
  wc, hc = barcoordinates(heights)
1295
- horizontal = kv[:horizontal] || false
1296
1314
  create_plot(:bar, labels, heights, kv) do |plt|
1297
- if horizontal
1315
+ if kv[:horizontal]
1298
1316
  plt.args = [[hc, wc, nil, nil, '']]
1299
1317
  plt.kvs[:yticks] = [1, 1]
1300
1318
  plt.kvs[:yticklabels] = labels
@@ -1307,11 +1325,15 @@ module GR
1307
1325
  end
1308
1326
 
1309
1327
  # (Plot) Draw a histogram.
1310
- def histogram(x, kv = {})
1311
- create_plot(:hist, x, kv) do |plt|
1328
+ def histogram(series, kv = {})
1329
+ create_plot(:hist, series, kv) do |plt|
1312
1330
  nbins = plt.kvs[:nbins] || 0
1313
- x, y = hist(x, nbins)
1314
- 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
1315
1337
  end
1316
1338
  end
1317
1339
 
@@ -1337,7 +1359,7 @@ module GR
1337
1359
  end
1338
1360
 
1339
1361
  # Set current subplot index.
1340
- def subplot(nr, nc, p)
1362
+ def subplot(nr, nc, p, kv = {})
1341
1363
  xmin = 1
1342
1364
  xmax = 0
1343
1365
  ymin = 1
@@ -1353,9 +1375,10 @@ module GR
1353
1375
  end
1354
1376
  {
1355
1377
  subplot: [xmin, xmax, ymin, ymax],
1378
+ # The policy of clearing when p[0]==1 is controversial
1356
1379
  clear: p[0] == 1,
1357
1380
  update: p[-1] == nr * nc
1358
- }
1381
+ }.merge kv
1359
1382
  end
1360
1383
 
1361
1384
  # (Plot) Save the current figure to a file.