ruby-gr 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/gr/ffi.rb CHANGED
@@ -1,198 +1,206 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ffi'
3
+ require 'fiddle/import'
4
4
 
5
5
  module GR
6
6
  # FFI Wrapper module for GR
7
7
  module FFI
8
- extend ::FFI::Library
8
+ extend Fiddle::Importer
9
9
 
10
10
  begin
11
- ffi_lib GR.ffi_lib
11
+ dlload GR.ffi_lib
12
12
  rescue LoadError
13
13
  raise LoadError, 'Could not find GR Framework'
14
14
  end
15
15
 
16
- extend GRCommons::AttachFunction
16
+ extend GRCommons::Extern
17
17
 
18
18
  # https://github.com/sciapp/gr/blob/master/lib/gr/gr.h
19
19
 
20
- attach_function :gr_initgr, %i[], :void
21
- attach_function :gr_opengks, %i[], :void
22
- attach_function :gr_closegks, %i[], :void
23
- attach_function :gr_inqdspsize, %i[pointer pointer pointer pointer], :void
24
- attach_function :gr_openws, %i[int string int], :void
25
- attach_function :gr_closews, %i[int], :void
26
- attach_function :gr_activatews, %i[int], :void
27
- attach_function :gr_deactivatews, %i[int], :void
28
- attach_function :gr_configurews, %i[], :void
29
- attach_function :gr_clearws, %i[], :void
30
- attach_function :gr_updatews, %i[], :void
31
- attach_function :gr_polyline, %i[int pointer pointer], :void
32
- attach_function :gr_polymarker, %i[int pointer pointer], :void
33
- attach_function :gr_text, %i[double double string], :void
34
- attach_function :gr_inqtext, %i[double double string pointer pointer], :void
35
- attach_function :gr_fillarea, %i[int pointer pointer], :void
36
- attach_function :gr_cellarray, %i[double double double double int int int int int int pointer], :void
37
- attach_function :gr_nonuniformcellarray, %i[pointer pointer int int int int int int pointer], :void
38
- attach_function :gr_polarcellarray, %i[double double double double double double int int int int int int pointer], :void
39
- attach_function :gr_gdp, %i[int pointer pointer int int pointer], :void
40
- attach_function :gr_spline, %i[int pointer pointer int int], :void
41
- attach_function :gr_gridit, %i[int pointer pointer pointer int int pointer pointer pointer], :void
42
- attach_function :gr_setlinetype, %i[int], :void
43
- attach_function :gr_inqlinetype, %i[pointer], :void
44
- attach_function :gr_setlinewidth, %i[double], :void
45
- attach_function :gr_inqlinewidth, %i[pointer], :void
46
- attach_function :gr_setlinecolorind, %i[int], :void
47
- attach_function :gr_inqlinecolorind, %i[pointer], :void
48
- attach_function :gr_setmarkertype, %i[int], :void
49
- attach_function :gr_inqmarkertype, %i[pointer], :void
50
- attach_function :gr_setmarkersize, %i[double], :void
51
- attach_function :gr_inqmarkersize, %i[pointer], :void
52
- attach_function :gr_setmarkercolorind, %i[int], :void
53
- attach_function :gr_inqmarkercolorind, %i[pointer], :void
54
- attach_function :gr_settextfontprec, %i[int int], :void
55
- attach_function :gr_setcharexpan, %i[double], :void
56
- attach_function :gr_setcharspace, %i[double], :void
57
- attach_function :gr_settextcolorind, %i[int], :void
58
- attach_function :gr_setcharheight, %i[double], :void
59
- attach_function :gr_setcharup, %i[double double], :void
60
- attach_function :gr_settextpath, %i[int], :void
61
- attach_function :gr_settextalign, %i[int int], :void
62
- attach_function :gr_setfillintstyle, %i[int], :void
63
- attach_function :gr_inqfillintstyle, %i[pointer], :void
64
- attach_function :gr_setfillstyle, %i[int], :void
65
- attach_function :gr_inqfillstyle, %i[pointer], :void
66
- attach_function :gr_setfillcolorind, %i[int], :void
67
- attach_function :gr_inqfillcolorind, %i[pointer], :void
68
- attach_function :gr_setcolorrep, %i[int double double double], :void
69
- attach_function :gr_setscale, %i[int], :int
70
- attach_function :gr_inqscale, %i[pointer], :void
71
- attach_function :gr_setwindow, %i[double double double double], :void
72
- attach_function :gr_inqwindow, %i[pointer pointer pointer pointer], :void
73
- attach_function :gr_setviewport, %i[double double double double], :void
74
- attach_function :gr_inqviewport, %i[pointer pointer pointer pointer], :void
75
- attach_function :gr_selntran, %i[int], :void
76
- attach_function :gr_setclip, %i[int], :void
77
- attach_function :gr_setwswindow, %i[double double double double], :void
78
- attach_function :gr_setwsviewport, %i[double double double double], :void
79
- attach_function :gr_createseg, %i[int], :void
80
- attach_function :gr_copysegws, %i[int], :void
81
- attach_function :gr_redrawsegws, %i[], :void
82
- attach_function :gr_setsegtran, %i[int double double double double double double double], :void
83
- attach_function :gr_closeseg, %i[], :void
84
- attach_function :gr_emergencyclosegks, %i[], :void
85
- attach_function :gr_updategks, %i[], :void
86
- attach_function :gr_setspace, %i[double double int int], :int
87
- attach_function :gr_inqspace, %i[pointer pointer pointer pointer], :void
88
- attach_function :gr_textext, %i[double double string], :int
89
- attach_function :gr_inqtextext, %i[double double string pointer pointer], :void
90
- attach_function :gr_axes, %i[double double double double int int double], :void
91
- # attach_function :gr_axeslbl
92
- attach_function :gr_grid, %i[double double double double int int], :void
93
- attach_function :gr_grid3d, %i[double double double double double double int int int], :void
94
- attach_function :gr_verrorbars, %i[int pointer pointer pointer pointer], :void
95
- attach_function :gr_herrorbars, %i[int pointer pointer pointer pointer], :void
96
- attach_function :gr_polyline3d, %i[int pointer pointer pointer], :void
97
- attach_function :gr_polymarker3d, %i[int pointer pointer pointer], :void
98
- attach_function :gr_axes3d, %i[double double double double double double int int int double], :void
99
- attach_function :gr_titles3d, %i[string string string], :void
100
- attach_function :gr_surface, %i[int int pointer pointer pointer int], :void
101
- attach_function :gr_contour, %i[int int int pointer pointer pointer pointer int], :void
102
- attach_function :gr_contourf, %i[int int int pointer pointer pointer pointer int], :void
103
- attach_function :gr_tricontour, %i[int pointer pointer pointer int pointer], :void
104
- attach_function :gr_hexbin, %i[int pointer pointer int], :int
105
- attach_function :gr_setcolormap, %i[int], :void
106
- attach_function :gr_inqcolormap, %i[pointer], :void
107
- attach_function :gr_setcolormapfromrgb, %i[int pointer pointer pointer pointer], :void
108
- attach_function :gr_colorbar, %i[], :void
109
- attach_function :gr_inqcolor, %i[int pointer], :void
110
- attach_function :gr_inqcolorfromrgb, %i[double double double], :int
111
- attach_function :gr_hsvtorgb, %i[double double double pointer pointer pointer], :void
112
- attach_function :gr_tick, %i[double double], :double
113
- attach_function :gr_validaterange, %i[double double], :int
114
- attach_function :gr_adjustlimits, %i[pointer pointer], :void
115
- attach_function :gr_adjustrange, %i[pointer pointer], :void
116
- attach_function :gr_beginprint, %i[string], :void
117
- attach_function :gr_beginprintext, %i[string string string string], :void
118
- attach_function :gr_endprint, %i[], :void
119
- attach_function :gr_ndctowc, %i[pointer pointer], :void
120
- attach_function :gr_wctondc, %i[pointer pointer], :void
121
- attach_function :gr_wc3towc, %i[pointer pointer pointer], :void
122
- attach_function :gr_drawrect, %i[double double double double], :void
123
- attach_function :gr_fillrect, %i[double double double double], :void
124
- attach_function :gr_drawarc, %i[double double double double double double], :void
125
- attach_function :gr_fillarc, %i[double double double double double double], :void
126
- attach_function :gr_drawpath, %i[int pointer pointer int], :void
127
- attach_function :gr_setarrowstyle, %i[int], :void
128
- attach_function :gr_setarrowsize, %i[double], :void
129
- attach_function :gr_drawarrow, %i[double double double double], :void
130
- attach_function :gr_readimage, %i[string pointer pointer pointer], :int
131
- attach_function :gr_drawimage, %i[double double double double int int pointer int], :void
132
- attach_function :gr_importgraphics, %i[string], :int
133
- attach_function :gr_setshadow, %i[double double double], :void
134
- attach_function :gr_settransparency, %i[double], :void
135
- attach_function :gr_setcoordxform, %i[pointer], :void
136
- attach_function :gr_begingraphics, %i[string], :void
137
- attach_function :gr_endgraphics, %i[], :void
138
- attach_function :gr_getgraphics, %i[], :string
139
- attach_function :gr_drawgraphics, %i[string], :int
140
- attach_function :gr_mathtex, %i[double double string], :void
141
- attach_function :gr_inqmathtex, %i[double double string pointer pointer], :void
142
- attach_function :gr_beginselection, %i[int int], :void
143
- attach_function :gr_endselection, %i[], :void
144
- attach_function :gr_moveselection, %i[double double], :void
145
- attach_function :gr_resizeselection, %i[int double double], :void
146
- attach_function :gr_inqbbox, %i[pointer pointer pointer pointer], :void
147
- attach_function :gr_precision, %i[], :double
148
- attach_function :gr_setregenflags, %i[int], :void
149
- attach_function :gr_inqregenflags, %i[], :int
150
- attach_function :gr_savestate, %i[], :void
151
- attach_function :gr_restorestate, %i[], :void
152
- attach_function :gr_selectcontext, %i[int], :void
153
- attach_function :gr_destroycontext, %i[int], :void
154
- attach_function :gr_uselinespec, %i[string], :int
155
- # attach_function :gr_delaunay, %i[int pointer pointer pointer pointer], :void
156
- attach_function :gr_reducepoints, %i[int pointer pointer int pointer pointer], :void
157
- attach_function :gr_trisurface, %i[int pointer pointer pointer], :void
158
- attach_function :gr_gradient, %i[int int pointer pointer pointer pointer pointer], :void
159
- attach_function :gr_quiver, %i[int int pointer pointer pointer pointer int], :void
160
- attach_function :gr_interp2, %i[int int pointer pointer pointer int int pointer pointer pointer int double], :void
20
+ extern 'void gr_initgr(void)'
21
+ extern 'void gr_opengks(void)'
22
+ extern 'void gr_closegks(void)'
23
+ extern 'void gr_inqdspsize(double *, double *, int *, int *)'
24
+ extern 'void gr_openws(int, char *, int)'
25
+ extern 'void gr_closews(int)'
26
+ extern 'void gr_activatews(int)'
27
+ extern 'void gr_deactivatews(int)'
28
+ extern 'void gr_configurews(void)'
29
+ extern 'void gr_clearws(void)'
30
+ extern 'void gr_updatews(void)'
31
+ extern 'void gr_polyline(int, double *, double *)'
32
+ extern 'void gr_polymarker(int, double *, double *)'
33
+ extern 'void gr_text(double, double, char *)'
34
+ extern 'void gr_inqtext(double, double, char *, double *, double *)'
35
+ extern 'void gr_fillarea(int, double *, double *)'
36
+ extern 'void gr_cellarray(double, double, double, double, ' \
37
+ 'int, int, int, int, int, int, int *)'
38
+ extern 'void gr_nonuniformcellarray(double *, double *, ' \
39
+ 'int, int, int, int, int, int, int *)'
40
+ extern 'void gr_polarcellarray(double, double, double, double, double, double, ' \
41
+ 'int, int, int, int, int, int, int *)'
42
+ extern 'void gr_gdp(int, double *, double *, int, int, int *)'
43
+ extern 'void gr_spline(int, double *, double *, int, int)'
44
+ extern 'void gr_gridit(int, double *, double *, double *, int, int, ' \
45
+ 'double *, double *, double *)'
46
+ extern 'void gr_setlinetype(int)'
47
+ extern 'void gr_inqlinetype(int *)'
48
+ extern 'void gr_setlinewidth(double)'
49
+ extern 'void gr_inqlinewidth(double *)'
50
+ extern 'void gr_setlinecolorind(int)'
51
+ extern 'void gr_inqlinecolorind(int *)'
52
+ extern 'void gr_setmarkertype(int)'
53
+ extern 'void gr_inqmarkertype(int *)'
54
+ extern 'void gr_setmarkersize(double)'
55
+ extern 'void gr_inqmarkersize(double *)'
56
+ extern 'void gr_setmarkercolorind(int)'
57
+ extern 'void gr_inqmarkercolorind(int *)'
58
+ extern 'void gr_settextfontprec(int, int)'
59
+ extern 'void gr_setcharexpan(double)'
60
+ extern 'void gr_setcharspace(double)'
61
+ extern 'void gr_settextcolorind(int)'
62
+ extern 'void gr_setcharheight(double)'
63
+ extern 'void gr_setcharup(double, double)'
64
+ extern 'void gr_settextpath(int)'
65
+ extern 'void gr_settextalign(int, int)'
66
+ extern 'void gr_setfillintstyle(int)'
67
+ extern 'void gr_inqfillintstyle(int *)'
68
+ extern 'void gr_setfillstyle(int)'
69
+ extern 'void gr_inqfillstyle(int *)'
70
+ extern 'void gr_setfillcolorind(int)'
71
+ extern 'void gr_inqfillcolorind(int *)'
72
+ extern 'void gr_setcolorrep(int, double, double, double)'
73
+ extern 'void gr_setwindow(double, double, double, double)'
74
+ extern 'void gr_inqwindow(double *, double *, double *, double *)'
75
+ extern 'void gr_setviewport(double, double, double, double)'
76
+ extern 'void gr_inqviewport(double *, double *, double *, double *)'
77
+ extern 'void gr_selntran(int)'
78
+ extern 'void gr_setclip(int)'
79
+ extern 'void gr_setwswindow(double, double, double, double)'
80
+ extern 'void gr_setwsviewport(double, double, double, double)'
81
+ extern 'void gr_createseg(int)'
82
+ extern 'void gr_copysegws(int)'
83
+ extern 'void gr_redrawsegws(void)'
84
+ extern 'void gr_setsegtran(int, double, double, double, double, double, double, double)'
85
+ extern 'void gr_closeseg(void)'
86
+ extern 'void gr_emergencyclosegks(void)'
87
+ extern 'void gr_updategks(void)'
88
+ extern 'int gr_setspace(double, double, int, int)'
89
+ extern 'void gr_inqspace(double *, double *, int *, int *)'
90
+ extern 'int gr_setscale(int)'
91
+ extern 'void gr_inqscale(int *)'
92
+ extern 'int gr_textext(double, double, char *)'
93
+ extern 'void gr_inqtextext(double, double, char *, double *, double *)'
94
+ extern 'void gr_axes(double, double, double, double, int, int, double)'
95
+ extern 'void gr_axeslbl(double, double, double, double, int, int, double,' \
96
+ 'void (*)(double, double, const char *, double),' \
97
+ 'void (*)(double, double, const char *, double))'
98
+ extern 'void gr_grid(double, double, double, double, int, int)'
99
+ extern 'void gr_grid3d(double, double, double, double, double, double, int, int, int)'
100
+ extern 'void gr_verrorbars(int, double *, double *, double *, double *)'
101
+ extern 'void gr_herrorbars(int, double *, double *, double *, double *)'
102
+ extern 'void gr_polyline3d(int, double *, double *, double *)'
103
+ extern 'void gr_polymarker3d(int, double *, double *, double *)'
104
+ extern 'void gr_axes3d(double, double, double, double, double, double, int, int, int, double)'
105
+ extern 'void gr_titles3d(char *, char *, char *)'
106
+ extern 'void gr_surface(int, int, double *, double *, double *, int)'
107
+ extern 'void gr_contour(int, int, int, double *, double *, double *, double *, int)'
108
+ extern 'void gr_contourf(int, int, int, double *, double *, double *, double *, int)'
109
+ extern 'void gr_tricontour(int, double *, double *, double *, int, double *)'
110
+ extern 'int gr_hexbin(int, double *, double *, int)'
111
+ extern 'void gr_setcolormap(int)'
112
+ extern 'void gr_inqcolormap(int *)'
113
+ extern 'void gr_setcolormapfromrgb(int n, double *r, double *g, double *b, double *x)'
114
+ extern 'void gr_colorbar(void)'
115
+ extern 'void gr_inqcolor(int, int *)'
116
+ extern 'int gr_inqcolorfromrgb(double, double, double)'
117
+ extern 'void gr_hsvtorgb(double h, double s, double v, double *r, double *g, double *b)'
118
+ extern 'double gr_tick(double, double)'
119
+ extern 'int gr_validaterange(double, double)'
120
+ extern 'void gr_adjustlimits(double *, double *)'
121
+ extern 'void gr_adjustrange(double *, double *)'
122
+ extern 'void gr_beginprint(char *)'
123
+ extern 'void gr_beginprintext(char *, char *, char *, char *)'
124
+ extern 'void gr_endprint(void)'
125
+ extern 'void gr_ndctowc(double *, double *)'
126
+ extern 'void gr_wctondc(double *, double *)'
127
+ extern 'void gr_wc3towc(double *, double *, double *)'
128
+ extern 'void gr_drawrect(double, double, double, double)'
129
+ extern 'void gr_fillrect(double, double, double, double)'
130
+ extern 'void gr_drawarc(double, double, double, double, double, double)'
131
+ extern 'void gr_fillarc(double, double, double, double, double, double)'
132
+ extern 'void gr_drawpath(int, vertex_t *, unsigned char *, int)'
133
+ extern 'void gr_setarrowstyle(int)'
134
+ extern 'void gr_setarrowsize(double)'
135
+ extern 'void gr_drawarrow(double, double, double, double)'
136
+ extern 'int gr_readimage(char *, int *, int *, int **)'
137
+ extern 'void gr_drawimage(double, double, double, double, int, int, int *, int)'
138
+ extern 'int gr_importgraphics(char *)'
139
+ extern 'void gr_setshadow(double, double, double)'
140
+ extern 'void gr_settransparency(double)'
141
+ extern 'void gr_setcoordxform(double[3][2])'
142
+ extern 'void gr_begingraphics(char *)'
143
+ extern 'void gr_endgraphics(void)'
144
+ extern 'char *gr_getgraphics(void)'
145
+ extern 'int gr_drawgraphics(char *)'
146
+ extern 'void gr_mathtex(double, double, char *)'
147
+ extern 'void gr_inqmathtex(double, double, char *, double *, double *)'
148
+ extern 'void gr_beginselection(int, int)'
149
+ extern 'void gr_endselection(void)'
150
+ extern 'void gr_moveselection(double, double)'
151
+ extern 'void gr_resizeselection(int, double, double)'
152
+ extern 'void gr_inqbbox(double *, double *, double *, double *)'
153
+ extern 'double gr_precision(void)'
154
+ extern 'void gr_setregenflags(int)'
155
+ extern 'int gr_inqregenflags(void)'
156
+ extern 'void gr_savestate(void)'
157
+ extern 'void gr_restorestate(void)'
158
+ extern 'void gr_selectcontext(int)'
159
+ extern 'void gr_destroycontext(int)'
160
+ extern 'int gr_uselinespec(char *)'
161
+ # extern 'void gr_delaunay(int, const double *, const double *, int *, int **)'
162
+ extern 'void gr_reducepoints(int, const double *, const double *, int, double *, double *)'
163
+ extern 'void gr_trisurface(int, double *, double *, double *)'
164
+ extern 'void gr_gradient(int, int, double *, double *, double *, double *, double *)'
165
+ extern 'void gr_quiver(int, int, double *, double *, double *, double *, int)'
166
+ extern 'void gr_interp2(int nx, int ny, const double *x, const double *y, const double *z,' \
167
+ 'int nxq, int nyq, const double *xq, const double *yq, double *zq, int method, double extrapval)'
168
+ # extern :gr_newmeta
169
+ # extern :gr_deletemeta
170
+ # extern :gr_finalizemeta
171
+ # extern :gr_meta_args_push
172
+ # extern :gr_meta_args_push_buf
173
+ # extern :gr_meta_args_contains
174
+ # extern :gr_meta_args_clear
175
+ # extern :gr_meta_args_remove
176
+ # extern :gr_meta_get_box
177
+ # extern :gr_openmeta
178
+ # extern :gr_recvmeta
179
+ # extern :gr_sendmeta
180
+ # extern :gr_sendmeta_buf
181
+ # extern :gr_sendmeta_ref
182
+ # extern :gr_sendmeta_args
183
+ # extern :gr_closemeta
184
+ # extern :gr_clearmeta
185
+ # extern :gr_inputmeta
186
+ # extern :gr_mergemeta
187
+ # extern :gr_plotmeta
188
+ # extern :gr_readmeta
189
+ # extern :gr_switchmeta
190
+ # extern :gr_registermeta
191
+ # extern :gr_unregistermeta
192
+ # extern :gr_meta_max_plotid
193
+ # extern :gr_dumpmeta
194
+ # extern :gr_dumpmeta_json
161
195
 
162
- # attach_function :gr_newmeta
163
- # attach_function :gr_deletemeta
164
- # attach_function :gr_finalizemeta
165
- # attach_function :gr_meta_args_push
166
- # attach_function :gr_meta_args_push_buf
167
- # attach_function :gr_meta_args_contains
168
- # attach_function :gr_meta_args_clear
169
- # attach_function :gr_meta_args_remove
170
- # attach_function :gr_meta_get_box
171
- # attach_function :gr_openmeta
172
- # attach_function :gr_recvmeta
173
- # attach_function :gr_sendmeta
174
- # attach_function :gr_sendmeta_buf
175
- # attach_function :gr_sendmeta_ref
176
- # attach_function :gr_sendmeta_args
177
- # attach_function :gr_closemeta
178
- # attach_function :gr_clearmeta
179
- # attach_function :gr_inputmeta
180
- # attach_function :gr_mergemeta
181
- # attach_function :gr_plotmeta
182
- # attach_function :gr_readmeta
183
- # attach_function :gr_switchmeta
184
- # attach_function :gr_registermeta
185
- # attach_function :gr_unregistermeta
186
- # attach_function :gr_meta_max_plotid
187
- # attach_function :gr_dumpmeta
188
- # attach_function :gr_dumpmeta_json
189
-
190
- attach_function :gr_version, %i[], :pointer
191
- attach_function :gr_shadepoints, %i[int pointer pointer int int int], :void
192
- attach_function :gr_shadelines, %i[int pointer pointer int int int], :void
193
- attach_function :gr_panzoom, %i[double double double double pointer pointer pointer pointer], :void
194
- # attach_function :gr_findboundary
195
- attach_function :gr_setresamplemethod, %i[uint], :void
196
- attach_function :gr_inqresamplemethod, %i[pointer], :void
196
+ extern 'const char *gr_version(void)'
197
+ extern 'void gr_shade(int, double *, double *, int, int, double *, int, int, int *)'
198
+ extern 'void gr_shadepoints(int, double *, double *, int, int, int)'
199
+ extern 'void gr_shadelines(int, double *, double *, int, int, int)'
200
+ extern 'void gr_panzoom(double, double, double, double, double *, double *, double *, double *)'
201
+ # extern 'int gr_findboundary(int, double *, double *, double, double (*)(double, double), int, int *)'
202
+ extern 'void gr_setresamplemethod(unsigned int flag)'
203
+ extern 'void gr_inqresamplemethod(unsigned int *flag)'
204
+ extern 'void gr_path(int, double *, double *, char *)'
197
205
  end
198
206
  end
data/lib/gr/grbase.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GR
4
+ # This module automatically converts Ruby arrays and Numo::Narray into pointers.
4
5
  module GRBase
5
6
  extend GRCommons::DefineMethods
6
7
  define_ffi_methods(FFI,
data/lib/gr/plot.rb ADDED
@@ -0,0 +1,1344 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gr'
4
+ autoload :GR3, 'gr3'
5
+
6
+ # FIXME: Plot should not depend on Numo::Narrray unless the GR3 module is required.
7
+ require 'numo/narray'
8
+
9
+ module GR
10
+ class Plot # should be Figure ?
11
+ # Why is the Plot class NOT object-oriented?
12
+ #
13
+ # Because the code here is mainly ported from GR.jl.
14
+ # https://github.com/jheinen/GR.jl/blob/master/src/jlgr.jl
15
+ #
16
+ # The Python implementation is also Julia compliant.
17
+ # https://github.com/sciapp/python-gr
18
+ #
19
+ # Julia is not an object-oriented language (at least in 2019).
20
+ # So, you will see many if branches here.
21
+ # This is not the Ruby code style. But it WORKS.
22
+ #
23
+ # I want to thank the Josef Heinen(@jheinen), the creator of GR.jl
24
+ # and Florian Rhiem(@FlorianRhiem), the creator of python-gr.
25
+ #
26
+ # If you are interested in an object-oriented implementation,
27
+ # See rubyplot.
28
+ # https://github.com/SciRuby/rubyplot
29
+
30
+ # Plot kinds conform to GR.jl
31
+ PLOT_KIND = %i[line step scatter stem hist contour contourf hexbin heatmap
32
+ nonuniformheatmap wireframe surface plot3 scatter3 imshow
33
+ isosurface polar polarhist polarheatmap trisurf tricont shade
34
+ volume].freeze # the name might be changed in the future.
35
+
36
+ # Keyword options conform to GR.jl.
37
+ KW_ARGS = %i[accelerate algorithm alpha backgroundcolor barwidth baseline
38
+ clabels color colormap figsize isovalue labels levels location
39
+ nbins rotation size tilt title where xflip xform xlabel xlim
40
+ xlog yflip ylabel ylim ylog zflip zlabel zlim zlog clim
41
+ subplot].freeze
42
+
43
+ def initialize(*args)
44
+ @kvs = if args[-1].is_a? Hash
45
+ args.pop
46
+ else
47
+ {}
48
+ end
49
+ @args = plot_args(args) # method name is the same as Julia/Python
50
+ @kvs[:size] ||= [600, 450]
51
+ @kvs[:ax] ||= false
52
+ @kvs[:subplot] ||= [0, 1, 0, 1]
53
+ @kvs[:clear] ||= true
54
+ @kvs[:update] ||= true
55
+ @scheme = 0
56
+ @background = 0xffffff
57
+ @handle = nil
58
+ end
59
+ attr_accessor :args, :kvs, :scheme
60
+
61
+ def set_viewport(kind, subplot)
62
+ mwidth, mheight, width, height = GR.inqdspsize
63
+ if kvs[:figsize]
64
+ w = 0.0254 * width * kvs[:figsize][0] / mwidth
65
+ h = 0.0254 * height * kvs[:figsize][1] / mheight
66
+ else
67
+ dpi = width / mwidth * 0.0254
68
+ if dpi > 200
69
+ w, h = kvs[:size].map { |x| x * dpi / 100 }
70
+ else
71
+ w, h = kvs[:size]
72
+ end
73
+ end
74
+ viewport = [0, 0, 0, 0]
75
+ vp = subplot.clone
76
+ if w > h
77
+ ratio = h / w.to_f
78
+ msize = mwidth * w / width
79
+ GR.setwsviewport(0, msize, 0, msize * ratio)
80
+ GR.setwswindow(0, 1, 0, ratio)
81
+ vp[2] *= ratio
82
+ vp[3] *= ratio
83
+ else
84
+ ratio = w / h.to_f
85
+ msize = mheight * h / height
86
+ GR.setwsviewport(0, msize * ratio, 0, msize)
87
+ GR.setwswindow(0, ratio, 0, 1)
88
+ vp[0] *= ratio
89
+ vp[1] *= ratio
90
+ end
91
+ if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
92
+ extent = [vp[1] - vp[0], vp[3] - vp[2]].min
93
+ vp1 = 0.5 * (vp[0] + vp[1] - extent)
94
+ vp2 = 0.5 * (vp[0] + vp[1] + extent)
95
+ vp3 = 0.5 * (vp[2] + vp[3] - extent)
96
+ vp4 = 0.5 * (vp[2] + vp[3] + extent)
97
+ else
98
+ vp1, vp2, vp3, vp4 = vp
99
+ end
100
+ viewport[0] = vp1 + 0.125 * (vp2 - vp1)
101
+ viewport[1] = vp1 + 0.925 * (vp2 - vp1)
102
+ viewport[2] = vp3 + 0.125 * (vp4 - vp3)
103
+ viewport[3] = vp3 + 0.925 * (vp4 - vp3)
104
+ if %i[contour contourf hexbin heatmap nonuniformheatmap polarheatmap
105
+ surface trisurf volume].include?(kind)
106
+ viewport[1] -= 0.1
107
+ end
108
+
109
+ if %i[line step scatter stem].include?(kind) && kvs[:labels]
110
+ location = kvs[:location] || 1
111
+ if [11, 12, 13].include?(location)
112
+ w, h = legend_size
113
+ viewport[1] -= w + 0.1
114
+ end
115
+ end
116
+
117
+ GR.setviewport(viewport[0], viewport[1], viewport[2], viewport[3])
118
+
119
+ kvs[:viewport] = viewport
120
+ kvs[:vp] = vp
121
+ kvs[:ratio] = ratio
122
+
123
+ if kvs[:backgroundcolor]
124
+ GR.savestate
125
+ GR.selntran(0)
126
+ GR.setfillintstyle(GR::INTSTYLE_SOLID)
127
+ GR.setfillcolorind(kvs[:backgroundcolor])
128
+ if w > h
129
+ GR.fillrect(subplot[0], subplot[1],
130
+ ratio * subplot[2], ratio * subplot[3])
131
+ else
132
+ GR.fillrect(ratio * subplot[0], ratio * subplot[1],
133
+ subplot[2], subplot[3])
134
+ end
135
+ GR.selntran(1)
136
+ GR.restorestate
137
+ end
138
+
139
+ if %i[polar polarhist polarheatmap].include? kind
140
+ xmin, xmax, ymin, ymax = viewport
141
+ xcenter = 0.5 * (xmin + xmax)
142
+ ycenter = 0.5 * (ymin + ymax)
143
+ r = 0.5 * [xmax - xmin, ymax - ymin].min
144
+ GR.setviewport(xcenter - r, xcenter + r, ycenter - r, ycenter + r)
145
+ end
146
+ end
147
+
148
+ def set_window(kind)
149
+ scale = 0
150
+ unless %i[polar polarhist polarheatmap].include?(kind)
151
+ scale |= GR::OPTION_X_LOG if kvs[:xlog]
152
+ scale |= GR::OPTION_Y_LOG if kvs[:ylog]
153
+ scale |= GR::OPTION_Z_LOG if kvs[:zlog]
154
+ scale |= GR::OPTION_FLIP_X if kvs[:xflip]
155
+ scale |= GR::OPTION_FLIP_Y if kvs[:yflip]
156
+ scale |= GR::OPTION_FLIP_Z if kvs[:zflip]
157
+ end
158
+ if kvs.key?(:panzoom)
159
+ xmin, xmax, ymin, ymax = GR.panzoom(*kvs[:panzoom])
160
+ kvs[:xrange] = [xmin, xmax]
161
+ kvs[:yrange] = [ymin, ymax]
162
+ else
163
+ minmax
164
+ end
165
+
166
+ major_count = if %i[wireframe surface plot3 scatter3 polar polarhist
167
+ polarheatmap trisurf volume].include?(kind)
168
+ 2
169
+ else
170
+ 5
171
+ end
172
+
173
+ xmin, xmax = kvs[:xrange]
174
+ if (scale & GR::OPTION_X_LOG) == 0
175
+ xmin, xmax = GR.adjustlimits(xmin, xmax) unless kvs.key?(:xlim) || kvs.key?(:panzoom)
176
+ if kvs.key?(:xticks)
177
+ xtick, majorx = kvs[:xticks]
178
+ else
179
+ majorx = major_count
180
+ xtick = GR.tick(xmin, xmax) / majorx
181
+ end
182
+ else
183
+ xtick = majorx = 1
184
+ end
185
+ xorg = if (scale & GR::OPTION_FLIP_X) == 0
186
+ [xmin, xmax]
187
+ else
188
+ [xmax, xmin]
189
+ end
190
+ kvs[:xaxis] = xtick, xorg, majorx
191
+
192
+ ymin, ymax = kvs[:yrange]
193
+ if kind == :hist && kvs.key?(:ylim)
194
+ ymin = (scale & GR::OPTION_Y_LOG) == 0 ? 0 : 1
195
+ end
196
+ if (scale & GR::OPTION_Y_LOG) == 0
197
+ ymin, ymax = GR.adjustlimits(ymin, ymax) unless kvs.key?(:ylim) || kvs.key?(:panzoom)
198
+ if kvs.key?(:yticks)
199
+ ytick, majory = kvs[:yticks]
200
+ else
201
+ majory = major_count
202
+ ytick = GR.tick(ymin, ymax) / majory
203
+ end
204
+ else
205
+ ytick = majory = 1
206
+ end
207
+ yorg = if (scale & GR::OPTION_FLIP_Y) == 0
208
+ [ymin, ymax]
209
+ else
210
+ [ymax, ymin]
211
+ end
212
+ kvs[:yaxis] = ytick, yorg, majory
213
+
214
+ if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
215
+ zmin, zmax = kvs[:zrange]
216
+ if (scale & GR::OPTION_Z_LOG) == 0
217
+ zmin, zmax = GR.adjustlimits(zmin, zmax) if kvs.key?(:zlim)
218
+ if kvs.key?(:zticks)
219
+ ztick, majorz = kvs[:zticks]
220
+ else
221
+ majorz = major_count
222
+ ztick = GR.tick(zmin, zmax) / majorz
223
+ end
224
+ else
225
+ ztick = majorz = 1
226
+ end
227
+ zorg = if (scale & GR::OPTION_FLIP_Z) == 0
228
+ [zmin, zmax]
229
+ else
230
+ [zmax, zmin]
231
+ end
232
+ kvs[:zaxis] = ztick, zorg, majorz
233
+ end
234
+
235
+ kvs[:window] = xmin, xmax, ymin, ymax
236
+ if %i[polar polarhist polarheatmap].include?(kind)
237
+ GR.setwindow(-1, 1, -1, 1)
238
+ else
239
+ GR.setwindow(xmin, xmax, ymin, ymax)
240
+ end
241
+ if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
242
+ rotation = kvs[:rotation] || 40
243
+ tilt = kvs[:tilt] || 70
244
+ GR.setspace(zmin, zmax, rotation, tilt)
245
+ end
246
+
247
+ kvs[:scale] = scale
248
+ GR.setscale(scale)
249
+ end
250
+
251
+ def draw_axes(kind, pass = 1)
252
+ viewport = kvs[:viewport]
253
+ vp = kvs[:vp]
254
+ ratio = kvs[:ratio]
255
+ xtick, xorg, majorx = kvs[:xaxis]
256
+ ytick, yorg, majory = kvs[:yaxis]
257
+ drawgrid = kvs[:grid] || true
258
+ xtick = 10 if kvs[:scale] & GR::OPTION_X_LOG != 0
259
+ ytick = 10 if kvs[:scale] & GR::OPTION_Y_LOG != 0
260
+ GR.setlinecolorind(1)
261
+ diag = Math.sqrt((viewport[1] - viewport[0])**2 + (viewport[3] - viewport[2])**2)
262
+ GR.setlinewidth(1)
263
+ charheight = [0.018 * diag, 0.012].max
264
+ GR.setcharheight(charheight)
265
+ ticksize = 0.0075 * diag
266
+ if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
267
+ ztick, zorg, majorz = kvs[:zaxis]
268
+ if pass == 1 && drawgrid
269
+ GR.grid3d(xtick, 0, ztick, xorg[0], yorg[1], zorg[0], 2, 0, 2)
270
+ GR.grid3d(0, ytick, 0, xorg[0], yorg[1], zorg[0], 0, 2, 0)
271
+ else
272
+ GR.axes3d(xtick, 0, ztick, xorg[0], yorg[0], zorg[0], majorx, 0, majorz, -ticksize)
273
+ GR.axes3d(0, ytick, 0, xorg[1], yorg[0], zorg[0], 0, majory, 0, ticksize)
274
+ end
275
+ else
276
+ if %i[heatmap nonuniformheatmap shade].include?(kind)
277
+ ticksize = -ticksize
278
+ else
279
+ drawgrid && GR.grid(xtick, ytick, 0, 0, majorx, majory)
280
+ end
281
+ if kvs.key?(:xticklabels) || kvs.key?(:yticklabels)
282
+ fx = if kvs.key?(:xticklabels)
283
+ GRCommons::Fiddley::Function.new(
284
+ :void, %i[double double string double]
285
+ ) do |x, y, _svalue, value|
286
+ label = value < 0 ? '' : kvs[:xticklabels][value] || ''
287
+ GR.textext(x, y, label)
288
+ end
289
+ else
290
+ GRCommons::Fiddley::Function.new(
291
+ :void, %i[double double string double]
292
+ ) do |x, y, _svalue, value|
293
+ GR.textext(x, y, value.to_s)
294
+ end
295
+ end
296
+ fy = if kvs.key?(:yticklabels)
297
+ GRCommons::Fiddley::Function.new(
298
+ :void, %i[double double string double]
299
+ ) do |x, y, _svalue, value|
300
+ label = value < 0 ? '' : kvs[:yticklabels][value] || ''
301
+ GR.textext(x, y, label)
302
+ end
303
+ else
304
+ GRCommons::Fiddley::Function.new(
305
+ :void, %i[double double string double]
306
+ ) do |x, y, _svalue, value|
307
+ GR.textext(x, y, value.to_s)
308
+ end
309
+ end
310
+ GR.axeslbl(xtick, ytick, xorg[0], yorg[0], majorx, majory, ticksize, fx, fy)
311
+ else
312
+ GR.axes(xtick, ytick, xorg[0], yorg[0], majorx, majory, ticksize)
313
+ end
314
+ GR.axes(xtick, ytick, xorg[1], yorg[1], -majorx, -majory, -ticksize)
315
+ end
316
+
317
+ if kvs.key?(:title)
318
+ GR.savestate
319
+ GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_TOP)
320
+ text(0.5 * (viewport[0] + viewport[1]), vp[3], kvs[:title])
321
+ GR.restorestate
322
+ end
323
+ if %i[wireframe surface plot3 scatter3 trisurf volume].include?(kind)
324
+ xlabel = kvs[:xlabel] || ''
325
+ ylabel = kvs[:ylabel] || ''
326
+ zlabel = kvs[:zlabel] || ''
327
+ GR.titles3d(xlabel, ylabel, zlabel)
328
+ else
329
+ if kvs.key?(:xlabel)
330
+ GR.savestate
331
+ GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_BOTTOM)
332
+ text(0.5 * (viewport[0] + viewport[1]), vp[2] + 0.5 * charheight, kvs[:xlabel])
333
+ GR.restorestate
334
+ end
335
+ if kvs.key?(:ylabel)
336
+ GR.savestate
337
+ GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_TOP)
338
+ GR.setcharup(-1, 0)
339
+ text(vp[0] + 0.5 * charheight, 0.5 * (viewport[2] + viewport[3]), kvs[:ylabel])
340
+ GR.restorestate
341
+ end
342
+ end
343
+ end
344
+
345
+ def draw_polar_axes
346
+ viewport = kvs[:viewport]
347
+ diag = Math.sqrt((viewport[1] - viewport[0])**2 + (viewport[3] - viewport[2])**2)
348
+ charheight = [0.018 * diag, 0.012].max
349
+
350
+ window = kvs[:window]
351
+ rmin = window[2]
352
+ rmax = window[3]
353
+
354
+ GR.savestate
355
+ GR.setcharheight(charheight)
356
+ GR.setlinetype(GR::LINETYPE_SOLID)
357
+
358
+ tick = 0.5 * GR.tick(rmin, rmax)
359
+ n = ((rmax - rmin) / tick + 0.5).round
360
+ (n + 1).times do |i|
361
+ r = i.to_f / n
362
+ if i.even?
363
+ GR.setlinecolorind(88)
364
+ GR.drawarc(-r, r, -r, r, 0, 359) if i > 0
365
+ GR.settextalign(GR::TEXT_HALIGN_LEFT, GR::TEXT_VALIGN_HALF)
366
+ x, y = GR.wctondc(0.05, r)
367
+ GR.text(x, y, (rmin + i * tick).to_s) # FIXME: round. significant digits.
368
+ else
369
+ GR.setlinecolorind(90)
370
+ GR.drawarc(-r, r, -r, r, 0, 359)
371
+ end
372
+ end
373
+ linspace(0, 315, 8).each do |alpha|
374
+ sinf = Math.sin(alpha * Math::PI / 180)
375
+ cosf = Math.cos(alpha * Math::PI / 180)
376
+ GR.polyline([cosf, 0], [sinf, 0])
377
+ GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_HALF)
378
+ x, y = GR.wctondc(1.1 * cosf, 1.1 * sinf)
379
+ GR.textext(x, y, "%<alpha>g\xb0")
380
+ end
381
+ GR.restorestate
382
+ end
383
+
384
+ def plot_polar(θ, ρ)
385
+ ρ = Numo::DFloat.cast(ρ) if ρ.is_a? Array
386
+ window = kvs[:window]
387
+ rmin = window[2]
388
+ rmax = window[3]
389
+ ρ = (ρ - rmin) / (rmax - rmin)
390
+ n = ρ.length
391
+ x = []
392
+ y = []
393
+ n.times do |i|
394
+ x << ρ[i] * Math.cos(θ[i])
395
+ y << ρ[i] * Math.sin(θ[i])
396
+ end
397
+ GR.polyline(x, y)
398
+ end
399
+
400
+ def plot_img(img)
401
+ viewport = kvs[:vp].clone
402
+ viewport[3] -= 0.05 if kvs.key?(:title)
403
+ vp = kvs[:vp]
404
+
405
+ if img.is_a? String
406
+ width, height, data = GR.readimage(img)
407
+ else
408
+ width, height = img.shape
409
+ cmin, cmax = kvs[:crange]
410
+ data = img.map { |i| normalize_color(i, cmin, cmax) }
411
+ data = data.map { |i| (1000 + i * 255).round }
412
+ end
413
+
414
+ if width * (viewport[3] - viewport[2]) < height * (viewport[1] - viewport[0])
415
+ w = width.to_f / height * (viewport[3] - viewport[2])
416
+ xmin = [0.5 * (viewport[0] + viewport[1] - w), viewport[0]].max
417
+ xmax = [0.5 * (viewport[0] + viewport[1] + w), viewport[1]].min
418
+ ymin = viewport[2]
419
+ ymax = viewport[3]
420
+ else
421
+ h = height.to_f / width * (viewport[1] - viewport[0])
422
+ xmin = viewport[0]
423
+ xmax = viewport[1]
424
+ ymin = [0.5 * (viewport[3] + viewport[2] - h), viewport[2]].max
425
+ ymax = [0.5 * (viewport[3] + viewport[2] + h), viewport[3]].min
426
+ end
427
+
428
+ GR.selntran(0)
429
+ GR.setscale(0)
430
+ if kvs.key?(:xflip)
431
+ tmp = xmax
432
+ xmax = xmin
433
+ xmin = tmp
434
+ end
435
+ if kvs.key?(:yflip)
436
+ tmp = ymax
437
+ ymax = ymin
438
+ ymin = tmp
439
+ end
440
+ if img.is_a? String
441
+ GR.drawimage(xmin, xmax, ymin, ymax, width, height, data)
442
+ else
443
+ GR.cellarray(xmin, xmax, ymin, ymax, width, height, data)
444
+ end
445
+
446
+ if kvs.key?(:title)
447
+ GR.savestate
448
+ GR.settextalign(GR::TEXT_HALIGN_CENTER, GR::TEXT_VALIGN_TOP)
449
+ text(0.5 * (viewport[0] + viewport[1]), vp[3], kvs[:title])
450
+ GR.restorestate
451
+ end
452
+ GR.selntran(1)
453
+ end
454
+
455
+ def plot_iso(v)
456
+ viewport = kvs[:viewport]
457
+
458
+ if viewport[3] - viewport[2] < viewport[1] - viewport[0]
459
+ width = viewport[3] - viewport[2]
460
+ centerx = 0.5 * (viewport[0] + viewport[1])
461
+ xmin = [centerx - 0.5 * width, viewport[0]].max
462
+ xmax = [centerx + 0.5 * width, viewport[1]].min
463
+ ymin = viewport[2]
464
+ ymax = viewport[3]
465
+ else
466
+ height = viewport[1] - viewport[0]
467
+ centery = 0.5 * (viewport[2] + viewport[3])
468
+ xmin = viewport[0]
469
+ xmax = viewport[1]
470
+ ymin = [centery - 0.5 * height, viewport[2]].max
471
+ ymax = [centery + 0.5 * height, viewport[3]].min
472
+ end
473
+
474
+ GR.selntran(0)
475
+ values = ((v - v.min) / (v.max - v.min) * (2 ^ 16 - 1)).round
476
+ nx, ny, nz = v.shape
477
+ isovalue = ((kvs[:isovalue] || 0.5) - v.min) / (v.max - v.min)
478
+ rotation = ((kvs[:rotation] || 40) * Math::PI / 180.0)
479
+ tilt = ((kvs[:tilt] || 70) * Math::PI / 180.0)
480
+ r = 2.5
481
+ GR3.clear
482
+ mesh = GR3.createisosurfacemesh(values, [2.0 / (nx - 1), 2.0 / (ny - 1), 2.0 / (nz - 1)],
483
+ [-1, -1, -1],
484
+ (isovalue * (2 ^ 16 - 1)).round)
485
+ color = kvs[:color] || [0.0, 0.5, 0.8]
486
+ GR3.setbackgroundcolor(1, 1, 1, 0)
487
+ GR3.drawmesh(mesh, 1, [0, 0, 0], [0, 0, 1], [0, 1, 0], color, [1, 1, 1])
488
+ GR3.cameralookat(r * Math.sin(tilt) * Math.sin(rotation),
489
+ r * Math.cos(tilt), r * Math.sin(tilt) * Math.cos(rotation),
490
+ 0, 0, 0, 0, 1, 0)
491
+ GR3.drawimage(xmin, xmax, ymin, ymax, 500, 500, GR3::DRAWABLE_GKS)
492
+ GR3.deletemesh(mesh)
493
+ GR.selntran(1)
494
+ end
495
+
496
+ def colorbar(off = 0, colors = 256)
497
+ GR.savestate
498
+ viewport = kvs[:viewport]
499
+ zmin, zmax = kvs[:zrange]
500
+ mask = (GR::OPTION_Z_LOG | GR::OPTION_FLIP_Y | GR::OPTION_FLIP_Z)
501
+ options = if kvs.key?(:zflip)
502
+ (GR.inqscale | GR::OPTION_FLIP_Y)
503
+ elsif kvs.key?(:yflip)
504
+ GR.inqscale & ~GR::OPTION_FLIP_Y
505
+ else
506
+ GR.inqscale
507
+ end
508
+ GR.setscale(options & mask)
509
+ h = 0.5 * (zmax - zmin) / (colors - 1)
510
+ GR.setwindow(0, 1, zmin, zmax)
511
+ GR.setviewport(viewport[1] + 0.02 + off, viewport[1] + 0.05 + off,
512
+ viewport[2], viewport[3])
513
+ l = linspace(1000, 1255, colors).map(&:round)
514
+ GR.cellarray(0, 1, zmax + h, zmin - h, 1, colors, l)
515
+ GR.setlinecolorind(1)
516
+ diag = Math.sqrt((viewport[1] - viewport[0])**2 + (viewport[3] - viewport[2])**2)
517
+ charheight = [0.016 * diag, 0.012].max
518
+ GR.setcharheight(charheight)
519
+ if kvs[:scale] & GR::OPTION_Z_LOG == 0
520
+ ztick = 0.5 * GR.tick(zmin, zmax)
521
+ GR.axes(0, ztick, 1, zmin, 0, 1, 0.005)
522
+ else
523
+ GR.setscale(GR::OPTION_Y_LOG)
524
+ GR.axes(0, 2, 1, zmin, 0, 1, 0.005)
525
+ end
526
+ GR.restorestate
527
+ end
528
+
529
+ def plot_data(_figure = true)
530
+ # GR.init
531
+
532
+ # target = GR.displayname
533
+ # if flag && target != None
534
+ # if target == "js" || target == "meta"
535
+ # send_meta(0)
536
+ # else
537
+ # send_serialized(target)
538
+ # end
539
+ # return
540
+ # end
541
+
542
+ kind = kvs[:kind] || :line
543
+ GR.clearws if kvs[:clear]
544
+
545
+ if scheme != 0
546
+ # Not yet.
547
+ end
548
+
549
+ set_viewport(kind, kvs[:subplot])
550
+ unless kvs[:ax]
551
+ set_window(kind)
552
+ if %i[polar polarhist].include?(kind)
553
+ draw_polar_axes
554
+ elsif !%i[imshow isosurface polarheatmap].include?(kind)
555
+ draw_axes(kind)
556
+ end
557
+ end
558
+
559
+ if kvs.key?(:colormap)
560
+ GR.setcolormap(kvs[:colormap])
561
+ else
562
+ GR.setcolormap(GR::COLORMAP_VIRIDIS)
563
+ end
564
+
565
+ GR.uselinespec(' ')
566
+ args.each do |x, y, z, c, spec|
567
+ # FIXME
568
+ spec ||= ''
569
+ GR.savestate
570
+ GR.settransparency(kvs[:alpha]) if kvs.key?(:alpha)
571
+ case kind
572
+ when :line
573
+ mask = GR.uselinespec(spec)
574
+ GR.polyline(x, y) if hasline(mask)
575
+ GR.polymarker(x, y) if hasmarker(mask)
576
+ when :step
577
+ mask = GR.uselinespec(spec)
578
+ if hasline(mask)
579
+ where = kvs[:where] || 'mid'
580
+ n = x.length
581
+ xs = [x[0]]
582
+ case where
583
+ when 'pre'
584
+ ys = [y[0]]
585
+ (n - 1).times do |i|
586
+ xs << x[i] << x[i + 1]
587
+ ys << y[i + 1] << y[i + 1]
588
+ end
589
+ when 'post'
590
+ ys = [y[0]]
591
+ (n - 1).times do |i|
592
+ xs << x[i + 1] << x[i + 1]
593
+ ys << y[i] << y[i + 1]
594
+ end
595
+ else
596
+ ys = []
597
+ (n - 1).times do |i|
598
+ xs << 0.5 * (x[i] + x[i + 1]) << 0.5 * (x[i] + x[i + 1])
599
+ ys << y[i] << y[i]
600
+ end
601
+ xs << x[n - 1]
602
+ ys << y[n - 1] << y[n - 1]
603
+ end
604
+ GR.polyline(xs, ys)
605
+ end
606
+ GR.polymarker(x, y) if hasmarker(mask)
607
+ when :scatter
608
+ GR.setmarkertype(GR::MARKERTYPE_SOLID_CIRCLE)
609
+ if z || c
610
+ if c
611
+ cmin, cmax = kvs[:crange]
612
+ c = c.to_a if narray?(c)
613
+ c.map! { |i| normalize_color(i, cmin, cmax) }
614
+ cind = c.map { |i| (1000 + i * 255).round }
615
+ end
616
+ x.length.times do |i|
617
+ GR.setmarkersize(z[i] / 100.0) if z
618
+ GR.setmarkercolorind(cind[i]) if c
619
+ GR.polymarker([x[i]], [y[i]])
620
+ end
621
+ else
622
+ GR.polymarker(x, y)
623
+ end
624
+ when :stem
625
+ GR.setlinecolorind(1)
626
+ GR.polyline(kvs[:window][0..1], [0, 0])
627
+ GR.setmarkertype(GR::MARKERTYPE_SOLID_CIRCLE)
628
+ GR.uselinespec(spec)
629
+ x = x.to_a if narray?(x)
630
+ y = y.to_a if narray?(y)
631
+ x.zip(y).each do |xi, yi|
632
+ GR.polyline([xi, xi], [0, yi])
633
+ end
634
+ GR.polymarker(x, y)
635
+ when :hist
636
+ ymin = kvs[:window][2]
637
+ y.length.times do |i|
638
+ GR.setfillcolorind(989)
639
+ GR.setfillintstyle(GR::INTSTYLE_SOLID)
640
+ GR.fillrect(x[i], x[i + 1], ymin, y[i])
641
+ GR.setfillcolorind(1)
642
+ GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
643
+ GR.fillrect(x[i], x[i + 1], ymin, y[i])
644
+ end
645
+ # when :polarhist
646
+ # xmin, xmax = x.minmax
647
+ # ymax = kvs[:window][3]
648
+ # ρ = y.map { |i| 2 * (i.to_f / ymax - 0.5) }
649
+ # θ = x.map { |i| 2 * Math::PI * (i.to_f - xmin) / (xmax - xmin) }
650
+ # ρ.length.times do |i|
651
+ # GR.setfillcolorind(989)
652
+ # GR.setfillintstyle(GR::INTSTYLE_SOLID)
653
+ # GR.fillarea([0, ρ[i] * Math.cos(θ[i]), ρ[i] * Math.cos(θ[i + 1])],
654
+ # [0, ρ[i] * Math.sin(θ[i]), ρ[i] * Math.sin(θ[i + 1])])
655
+ # GR.setfillcolorind(1)
656
+ # GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
657
+ # GR.fillarea([0, ρ[i] * Math.cos(θ[i]), ρ[i] * Math.cos(θ[i + 1])],
658
+ # [0, ρ[i] * Math.sin(θ[i]), ρ[i] * Math.sin(θ[i + 1])])
659
+ # end
660
+ when :polarheatmap
661
+ w, h = z.shape
662
+ cmap = colormap
663
+ cmin, cmax = kvs[:zrange]
664
+ data = z.map { |i| normalize_color(i, cmin, cmax) }
665
+ colors = data.map { |i| 1000 + i * 255 }
666
+ # if kvs[:xflip]
667
+ # if kvs[;yflip]
668
+ GR.polarcellarray(0, 0, 0, 360, 0, 1, w, h, colors)
669
+ draw_polar_axes
670
+ kvs[:zrange] = [cmin, cmax]
671
+ colorbar
672
+ when :contour
673
+ zmin, zmax = kvs[:zrange]
674
+ if x.length == y.length && y.length == z.length
675
+ x, y, z = GR.gridit(x, y, z, 200, 200)
676
+ zmin, zmax = kvs[:zlim] || z.compact.minmax # compact : removed nil
677
+ end
678
+ GR.setspace(zmin, zmax, 0, 90)
679
+ levels = kvs[:levels] || 0
680
+ clabels = kvs[:clabels] || false
681
+ if levels.is_a? Integer
682
+ hmin, hmax = GR.adjustrange(zmin, zmax)
683
+ h = linspace(hmin, hmax, levels == 0 ? 21 : levels + 1)
684
+ else
685
+ h = levels
686
+ end
687
+ GR.contour(x, y, h, z, clabels ? 1 : 1000)
688
+ colorbar(0, h.length)
689
+ when :contourf
690
+ zmin, zmax = kvs[:zrange]
691
+ if x.length == y.length && y.length == z.length
692
+ x, y, z = GR.gridit(x, y, z, 200, 200)
693
+ zmin, zmax = kvs[:zlim] || z.compact.minmax # compact : removed nil
694
+ end
695
+ GR.setspace(zmin, zmax, 0, 90)
696
+ levels = kvs[:levels] || 0
697
+ clabels = kvs[:clabels] || false
698
+ if levels.is_a? Integer
699
+ hmin, hmax = GR.adjustrange(zmin, zmax)
700
+ h = linspace(hmin, hmax, levels == 0 ? 21 : levels + 1)
701
+ else
702
+ h = levels
703
+ end
704
+ GR.contourf(x, y, h, z, clabels ? 1 : 0)
705
+ colorbar(0, h.length)
706
+ when :hexbin
707
+ nbins = kvs[:nbins] || 40
708
+ cntmax = GR.hexbin(x, y, nbins)
709
+ if cntmax > 0
710
+ kvs[:zrange] = [0, cntmax]
711
+ colorbar
712
+ end
713
+ when :heatmap, :nonuniformheatmap
714
+ case z
715
+ when Array
716
+ if z.all? { |zi| zi.size = z[0].size }
717
+ w = z.size
718
+ h = z[0].size
719
+ else
720
+ raise
721
+ end
722
+ when ->(obj) { narray?(obj) }
723
+ w, h = z.shape
724
+ else
725
+ raise
726
+ end
727
+ cmap = colormap
728
+ cmin, cmax = kvs[:crange]
729
+ levels = kvs[:levels] || 256
730
+ data = z.flatten.to_a.map { |i| normalize_color(i, cmin, cmax) } # NArray -> Array
731
+ if kind == :heatmap
732
+ rgba = data.map { |v| to_rgba(v, cmap) }
733
+ GR.drawimage(0.5, w + 0.5, h + 0.5, 0.5, w, h, rgba)
734
+ else
735
+ colors = data.map { |i| (1000 + i * 255).round }
736
+ GR.nonuniformcellarray(x, y, w, h, colors)
737
+ end
738
+ colorbar(0, levels)
739
+ when :wireframe
740
+ x, y, z = GR.gridit(x, y, z, 50, 50) if equal_length(x, y, z)
741
+ GR.setfillcolorind(0)
742
+ GR.surface(x, y, z, GR::OPTION_FILLED_MESH)
743
+ draw_axes(kind, 2)
744
+ when :surface
745
+ x, y, z = GR.gridit(x, y, z, 200, 200) if equal_length(x, y, z)
746
+ if kvs[:accelerate] == false
747
+ GR.surface(x, y, z, GR::OPTION_COLORED_MESH)
748
+ else
749
+ require 'gr3'
750
+ GR3.clear
751
+ GR3.surface(x, y, z, GR::OPTION_COLORED_MESH)
752
+ end
753
+ draw_axes(kind, 2)
754
+ colorbar(0.05)
755
+ when :volume
756
+ algorithm = kvs[:algorithm] || 0
757
+ require 'gr3'
758
+ GR3.clear
759
+ dmin, dmax = GR3.volume(z, algorithm)
760
+ draw_axes(kind, 2)
761
+ kvs[:zrange] = [dmin, dmax]
762
+ colorbar(0.05)
763
+ when :plot3
764
+ GR.polyline3d(x, y, z)
765
+ draw_axes(kind, 2)
766
+ when :scatter3
767
+ GR.setmarkertype(GR::MARKERTYPE_SOLID_CIRCLE)
768
+ if c
769
+ cmin, cmax = kvs[:crange]
770
+ c = c.map { |i| normalize_color(i, cmin, cmax) } # NArray -> Array
771
+ cind = c.map { |i| (1000 + i * 255).round }
772
+ x.length.times do |i|
773
+ GR.setmarkercolorind(cind[i])
774
+ GR.polymarker3d([x[i]], [y[i]], [z[i]])
775
+ end
776
+ else
777
+ GR.polymarker3d(x, y, z)
778
+ end
779
+ draw_axes(kind, 2)
780
+ when :imshow
781
+ plot_img(z)
782
+ when :isosurface
783
+ plot_iso(z)
784
+ when :polar
785
+ GR.uselinespec(spec)
786
+ plot_polar(x, y)
787
+ when :trisurf
788
+ GR.trisurface(x, y, z)
789
+ draw_axes(kind, 2)
790
+ colorbar(0.05)
791
+ when :tricont
792
+ zmin, zmax = kvs[:zrange]
793
+ levels = linspace(zmin, zmax, 20)
794
+ GR.tricontour(x, y, z, levels)
795
+ when :shade
796
+ xform = kvs[:xform] || 5
797
+ if x.to_a.include? Float::NAN # FIXME: Ruby is different from Julia?
798
+ # How to check NArray?
799
+ GR.shadelines(x, y, xform: xform)
800
+ else
801
+ GR.shadepoints(x, y, xform: xform)
802
+ end
803
+ when :bar
804
+ 0.step(x.length - 1, 2) do |i|
805
+ GR.setfillcolorind(989)
806
+ GR.setfillintstyle(GR::INTSTYLE_SOLID)
807
+ GR.fillrect(x[i], x[i + 1], y[i], y[i + 1])
808
+ GR.setfillcolorind(1)
809
+ GR.setfillintstyle(GR::INTSTYLE_HOLLOW)
810
+ GR.fillrect(x[i], x[i + 1], y[i], y[i + 1])
811
+ end
812
+ end
813
+ GR.restorestate
814
+ end
815
+
816
+ draw_legend if %i[line step scatter stem].include?(kind) && kvs.key?(:labels)
817
+
818
+ if kvs.key?(:update)
819
+ GR.updatews
820
+ # if GR.isinline()
821
+ # restore_context()
822
+ # return GR.show()
823
+ # end
824
+ end
825
+
826
+ # flag && restore_context()
827
+ end
828
+
829
+ def draw_legend
830
+ w, h = legend_size
831
+ viewport = kvs[:viewport]
832
+ location = kvs[:location] || 1
833
+ num_labels = kvs[:labels].length
834
+ GR.savestate
835
+ GR.selntran 0
836
+ GR.setscale 0
837
+ px = case location
838
+ when 11, 12, 13
839
+ viewport[1] + 0.11
840
+ when 8, 9, 10
841
+ 0.5 * (viewport[0] + viewport[1] - w + 0.05)
842
+ when 2, 3, 6
843
+ viewport[0] + 0.11
844
+ else
845
+ viewport[1] - 0.05 - w
846
+ end
847
+ py = case location
848
+ when 5, 6, 7, 10, 12
849
+ 0.5 * (viewport[2] + viewport[3] + h - 0.03)
850
+ when 13
851
+ viewport[2] + h
852
+ when 3, 4, 8
853
+ viewport[2] + h + 0.03
854
+ when 11
855
+ viewport[3] - 0.03
856
+ else
857
+ viewport[3] - 0.06
858
+ end
859
+ GR.setfillintstyle(GR::INTSTYLE_SOLID)
860
+ GR.setfillcolorind(0)
861
+ GR.fillrect(px - 0.08, px + w + 0.02, py + 0.03, py - h)
862
+ GR.setlinetype(GR::LINETYPE_SOLID)
863
+ GR.setlinecolorind(1)
864
+ GR.setlinewidth(1)
865
+ GR.drawrect(px - 0.08, px + w + 0.02, py + 0.03, py - h)
866
+ i = 0
867
+ GR.uselinespec(' ')
868
+ args.each do |_x, _y, _z, _c, spec|
869
+ if i < num_labels
870
+ label = kvs[:labels][i]
871
+ tbx, tby = inqtext(0, 0, label)
872
+ dy = [(tby[2] - tby[0]) - 0.03, 0].max
873
+ py -= 0.5 * dy
874
+ end
875
+ GR.savestate
876
+ mask = GR.uselinespec(spec || '')
877
+ GR.polyline([px - 0.07, px - 0.01], [py, py]) if hasline(mask)
878
+ GR.polymarker([px - 0.06, px - 0.02], [py, py]) if hasmarker(mask)
879
+ GR.restorestate
880
+ GR.settextalign(GR::TEXT_HALIGN_LEFT, GR::TEXT_VALIGN_HALF)
881
+ if i < num_labels
882
+ GR.text(px, py, label)
883
+ py -= 0.5 * dy
884
+ i += 1
885
+ end
886
+ py -= 0.03
887
+ GR.selntran(1)
888
+ GR.restorestate
889
+ end
890
+ end
891
+
892
+ private
893
+
894
+ def hasline(mask)
895
+ mask == 0x00 || (mask & 0x01 != 0)
896
+ end
897
+
898
+ def hasmarker(mask)
899
+ mask & 0x02 != 0
900
+ end
901
+
902
+ def colormap
903
+ # rgb
904
+ Array.new(256) do |colorind|
905
+ color = GR.inqcolor(1000 + colorind)
906
+ [(color & 0xff) / 255.0,
907
+ ((color >> 8) & 0xff) / 255.0,
908
+ ((color >> 16) & 0xff) / 255.0]
909
+ end
910
+ end
911
+
912
+ def to_rgba(value, cmap)
913
+ begin
914
+ r, g, b = cmap[(value * 255).round]
915
+ a = 1.0
916
+ rescue StandardError # nil
917
+ r = 0
918
+ g = 0
919
+ b = 0
920
+ a = 0
921
+ end
922
+
923
+ ((a * 255).round << 24) + ((b * 255).round << 16) +
924
+ ((g * 255).round << 8) + (r * 255).round
925
+ end
926
+
927
+ # https://gist.github.com/rysk-t/8d1aef0fb67abde1d259#gistcomment-1925021
928
+ def linspace(low, high, num)
929
+ [*0..(num - 1)].collect { |i| low + i.to_f * (high - low) / (num - 1) }
930
+ end
931
+
932
+ def plot_args(args, _fmt = :xys)
933
+ # :construction:
934
+ x, y, z, c = args
935
+ [[x, y, z, c]]
936
+ end
937
+
938
+ # Normalize a color c with the range [cmin, cmax]
939
+ # 0 <= normalize_color(c, cmin, cmax) <= 1
940
+ def normalize_color(c, cmin, cmax)
941
+ c = c.clamp(cmin, cmax) - cmin
942
+ c /= (cmax - cmin) if cmin != cmax
943
+ c
944
+ end
945
+
946
+ def inqtext(x, y, s)
947
+ if s.length >= 2 && s[0] == '$' && s[-1] == '$'
948
+ GR.inqmathtex(x, y, s[1..-2])
949
+ elsif s.include?('\\') || s.include?('_') || s.include?('^')
950
+ GR.inqtextext(x, y, s)
951
+ else
952
+ GR.inqtext(x, y, s)
953
+ end
954
+ end
955
+
956
+ def text(x, y, s)
957
+ if s.length >= 2 && s[0] == '$' && s[-1] == '$'
958
+ GR.mathtex(x, y, s[1..-2])
959
+ elsif s.include?('\\') || s.include?('_') || s.include?('^')
960
+ GR.textext(x, y, s)
961
+ else
962
+ GR.text(x, y, s)
963
+ end
964
+ end
965
+
966
+ def fix_minmax(a, b)
967
+ if a == b
968
+ a -= a != 0 ? 0.1 * a : 0.1
969
+ b += b != 0 ? 0.1 * b : 0.1
970
+ end
971
+ [a, b]
972
+ end
973
+
974
+ def minmax
975
+ xmin = ymin = zmin = cmin = Float::INFINITY
976
+ xmax = ymax = zmax = cmax = -Float::INFINITY
977
+
978
+ args.each do |x, y, z, c|
979
+ if x
980
+ x0, x1 = x.minmax
981
+ xmin = [x0, xmin].min
982
+ xmax = [x1, xmax].max
983
+ else
984
+ xmin = 0
985
+ xmax = 1
986
+ end
987
+ if y
988
+ y0, y1 = y.minmax
989
+ ymin = [y0, ymin].min
990
+ ymax = [y1, ymax].max
991
+ else
992
+ ymin = 0
993
+ ymax = 1
994
+ end
995
+ if z
996
+ z0, z1 = z.minmax
997
+ zmin = [z0, zmin].min
998
+ zmax = [z1, zmax].max
999
+ end
1000
+ if c
1001
+ c0, c1 = c.minmax
1002
+ cmin = [c0, cmin].min
1003
+ cmax = [c1, cmax].max
1004
+ elsif z
1005
+ z0, z1 = z.minmax
1006
+ cmin = [z0, zmin].min
1007
+ cmax = [z1, zmax].max
1008
+ end
1009
+ end
1010
+ xmin, xmax = fix_minmax(xmin, xmax)
1011
+ ymin, ymax = fix_minmax(ymin, ymax)
1012
+ zmin, zmax = fix_minmax(zmin, zmax)
1013
+ if kvs.key?(:xlim)
1014
+ x0, x1 = kvs[:xlim]
1015
+ x0 ||= xmin
1016
+ x1 ||= xmax
1017
+ kvs[:xrange] = [x0, x1]
1018
+ else
1019
+ kvs[:xrange] = [xmin, xmax]
1020
+ end
1021
+ if kvs.key?(:ylim)
1022
+ y0, y1 = kvs[:ylim]
1023
+ y0 ||= ymin
1024
+ y1 ||= ymax
1025
+ kvs[:yrange] = [y0, y1]
1026
+ else
1027
+ kvs[:yrange] = [ymin, ymax]
1028
+ end
1029
+ if kvs.key?(:zlim)
1030
+ z0, z1 = kvs[:zlim]
1031
+ z0 ||= zmin
1032
+ z1 ||= zmax
1033
+ kvs[:zrange] = [z0, z1]
1034
+ else
1035
+ kvs[:zrange] = [zmin, zmax]
1036
+ end
1037
+ if kvs.key?(:clim)
1038
+ c0, c1 = kvs[:clim]
1039
+ c0 ||= cmin
1040
+ c1 ||= cmax
1041
+ kvs[:crange] = [c0, c1]
1042
+ else
1043
+ kvs[:crange] = [cmin, cmax]
1044
+ end
1045
+ end
1046
+
1047
+ def legend_size
1048
+ scale = GR.inqscale
1049
+ GR.selntran(0)
1050
+ GR.setscale(0)
1051
+ w = 0
1052
+ h = 0
1053
+ kvs[:labels].each do |label|
1054
+ tbx, tby = inqtext(0, 0, label)
1055
+ w = [w, tbx[2]].max
1056
+ h += [tby[2] - tby[0], 0.03].max
1057
+ end
1058
+ GR.setscale(scale)
1059
+ GR.selntran(1)
1060
+ [w, h]
1061
+ end
1062
+
1063
+ # NOTE: duplicated definition (GRCommonUtils)
1064
+ def equal_length(*args)
1065
+ lengths = args.map(&:length)
1066
+ unless lengths.all? { |l| l == lengths[0] }
1067
+ raise ArgumentError,
1068
+ 'Sequences must have same length.'
1069
+ end
1070
+
1071
+ lengths[0]
1072
+ end
1073
+
1074
+ # NOTE: duplicated definition (GRCommonUtils)
1075
+ def narray?(data)
1076
+ defined?(Numo::NArray) && data.is_a?(Numo::NArray)
1077
+ end
1078
+ end
1079
+
1080
+ class << self
1081
+ def lineplot(*args)
1082
+ plt = GR::Plot.new(*args)
1083
+ plt.plot_data
1084
+ end
1085
+
1086
+ def stepplot(*args)
1087
+ plt = GR::Plot.new(*args)
1088
+ plt.kvs[:kind] = :step
1089
+ plt.plot_data
1090
+ end
1091
+
1092
+ def scatterplot(*args)
1093
+ plt = GR::Plot.new(*args)
1094
+ plt.kvs[:kind] = :scatter
1095
+ plt.plot_data
1096
+ end
1097
+
1098
+ def scatterplot3(*args)
1099
+ plt = GR::Plot.new(*args)
1100
+ plt.kvs[:kind] = :scatter3
1101
+ plt.plot_data
1102
+ end
1103
+
1104
+ def stemplot(*args)
1105
+ plt = GR::Plot.new(*args)
1106
+ plt.kvs[:kind] = :stem
1107
+ plt.plot_data
1108
+ end
1109
+
1110
+ def histogram(x, kv = {})
1111
+ plt = GR::Plot.new(x, kv)
1112
+ plt.kvs[:kind] = :hist
1113
+ nbins = plt.kvs[:nbins] || 0
1114
+ x, y = hist(x, nbins)
1115
+ plt.args = [[x, y, nil, nil, '']]
1116
+ plt.plot_data
1117
+ end
1118
+
1119
+ # def polarhistogram(x, kv = {})
1120
+ # plt = GR::Plot.new(x, kv)
1121
+ # plt.kvs[:kind] = :polarhist
1122
+ # nbins = plt.kvs[:nbins] || 0
1123
+ # x, y = hist(x, nbins)
1124
+ # plt.args = [[x, y, nil, nil, '']]
1125
+ # plt.plot_data
1126
+ # end
1127
+
1128
+ def heatmap(*args)
1129
+ plt = GR::Plot.new(*args)
1130
+ plt.kvs[:kind] = :heatmap
1131
+ # FIXME
1132
+ if narray?(args.first)
1133
+ z = args.first
1134
+ width, height = z.shape
1135
+ plt.kvs[:xlim] ||= [0.5, width + 0.5]
1136
+ plt.kvs[:ylim] ||= [0.5, height + 0.5]
1137
+ plt.args = [[[*1..width], [*1..height], z, nil, '']]
1138
+ else
1139
+ raise 'not implemented'
1140
+ end
1141
+ plt.plot_data
1142
+ end
1143
+
1144
+ def polarheatmap(*args)
1145
+ d = args.shift
1146
+ # FIXME
1147
+ z = Numo::DFloat.cast(d)
1148
+ raise 'expected 2-D array' unless z.ndim == 2
1149
+
1150
+ plt = GR::Plot.new(*args)
1151
+ plt.kvs[:kind] = :polarheatmap
1152
+ width, height = z.shape
1153
+ plt.kvs[:xlim] ||= [0.5, width + 0.5]
1154
+ plt.kvs[:ylim] ||= [0.5, height + 0.5]
1155
+ plt.args = [[(1..width).to_a, (1..height).to_a, z, nil, '']]
1156
+ plt.plot_data
1157
+ end
1158
+
1159
+ def contourplot(*args)
1160
+ kv = if args[-1].is_a? Hash
1161
+ args.pop
1162
+ else
1163
+ {}
1164
+ end
1165
+ if args.size == 1
1166
+ if args[0].is_a? Array
1167
+ z = Numo::DFloat.cast(args[0])
1168
+ xsize, ysize = z.shape
1169
+ elsif narray?(args[0])
1170
+ z = args[0]
1171
+ xsize, ysize = z.shape
1172
+ end
1173
+ x = (1..xsize).to_a
1174
+ y = (1..ysize).to_a
1175
+ elsif args.size == 3
1176
+ x, y, z = args
1177
+ else
1178
+ raise
1179
+ end
1180
+ plt = GR::Plot.new(x, y, z, kv)
1181
+ plt.kvs[:kind] = :contour
1182
+ plt.plot_data
1183
+ end
1184
+
1185
+ def contourfplot(*args)
1186
+ kv = if args[-1].is_a? Hash
1187
+ args.pop
1188
+ else
1189
+ {}
1190
+ end
1191
+ if args.size == 1
1192
+ if args[0].is_a? Array
1193
+ z = Numo::DFloat.cast(args[0])
1194
+ xsize, ysize = z.shape
1195
+ elsif narray?(args[0])
1196
+ z = args[0]
1197
+ xsize, ysize = z.shape
1198
+ end
1199
+ x = (1..xsize).to_a
1200
+ y = (1..ysize).to_a
1201
+ elsif args.size == 3
1202
+ x, y, z = args
1203
+ else
1204
+ raise
1205
+ end
1206
+ plt = GR::Plot.new(x, y, z, kv)
1207
+ plt.kvs[:kind] = :contourf
1208
+ plt.plot_data
1209
+ end
1210
+
1211
+ def hexbinplot(*args)
1212
+ plt = GR::Plot.new(*args)
1213
+ plt.kvs[:kind] = :hexbin
1214
+ plt.plot_data
1215
+ end
1216
+
1217
+ def tricontourplot(*args)
1218
+ plt = GR::Plot.new(*args)
1219
+ plt.kvs[:kind] = :tricont
1220
+ plt.plot_data
1221
+ end
1222
+
1223
+ def surfaceplot(*args)
1224
+ kv = if args[-1].is_a? Hash
1225
+ args.pop
1226
+ else
1227
+ {}
1228
+ end
1229
+ if args.size == 1
1230
+ if args[0].is_a? Array
1231
+ z = Numo::DFloat.cast(args[0])
1232
+ xsize, ysize = z.shape
1233
+ elsif narray?(args[0])
1234
+ z = args[0]
1235
+ xsize, ysize = z.shape
1236
+ end
1237
+ x = ([(1..xsize).to_a] * ysize).flatten
1238
+ y = ((1..ysize).to_a.map { |i| [i] * xsize }).flatten
1239
+ elsif args.size == 3
1240
+ x, y, z = args
1241
+ else
1242
+ raise
1243
+ end
1244
+ plt = GR::Plot.new(x, y, z, kv)
1245
+ plt.kvs[:kind] = :surface
1246
+ plt.plot_data
1247
+ end
1248
+
1249
+ def polarplot(*args)
1250
+ plt = GR::Plot.new(*args)
1251
+ plt.kvs[:kind] = :polar
1252
+ plt.plot_data
1253
+ end
1254
+
1255
+ def trisurfaceplot(*args)
1256
+ plt = GR::Plot.new(*args)
1257
+ plt.kvs[:kind] = :trisurf
1258
+ plt.plot_data
1259
+ end
1260
+
1261
+ def wireframe(*args)
1262
+ plt = GR::Plot.new(*args)
1263
+ plt.kvs[:kind] = :wireframe
1264
+ plt.plot_data
1265
+ end
1266
+
1267
+ def lineplot3(*args)
1268
+ plt = GR::Plot.new(*args)
1269
+ plt.kvs[:kind] = :plot3
1270
+ plt.plot_data
1271
+ end
1272
+
1273
+ # Note: GR.shade exists
1274
+ def shade(*args)
1275
+ plt = GR::Plot.new(*args)
1276
+ plt.kvs[:kind] = :shade
1277
+ plt.plot_data
1278
+ end
1279
+
1280
+ def volumeplot(v, kv = {})
1281
+ plt = GR::Plot.new(v, kv)
1282
+ plt.kvs[:kind] = :volume
1283
+ plt.args = [[nil, nil, v, nil, '']]
1284
+ plt.plot_data
1285
+ end
1286
+
1287
+ def barplot(labels, heights, kv = {})
1288
+ wc, hc = barcoordinates(heights)
1289
+ horizontal = kv[:horizontal] || false
1290
+ plt = GR::Plot.new(labels, heights, kv)
1291
+ plt.kvs[:kind] = :bar
1292
+ if horizontal
1293
+ plt.args = [[hc, wc, nil, nil, '']]
1294
+ plt.kvs[:yticks] = [1, 1]
1295
+ plt.kvs[:yticklabels] = labels
1296
+ else
1297
+ plt.args = [[wc, hc, nil, nil, '']]
1298
+ plt.kvs[:xticks] = [1, 1]
1299
+ plt.kvs[:xticklabels] = labels
1300
+ end
1301
+ plt.plot_data
1302
+ end
1303
+
1304
+ def imshow(img, kv = {})
1305
+ img = Numo::DFloat.cast(img) # Umm...
1306
+ plt = GR::Plot.new(kv)
1307
+ plt.kvs[:kind] = :imshow
1308
+ plt.args = [[nil, nil, img, nil, '']]
1309
+ plt.plot_data
1310
+ end
1311
+
1312
+ def isosurface(v, kv = {})
1313
+ v = Numo::DFloat.cast(v) # Umm...
1314
+ plt = GR::Plot.new(kv)
1315
+ plt.kvs[:kind] = :isosurface
1316
+ plt.args = [[nil, nil, v, nil, '']]
1317
+ plt.plot_data
1318
+ end
1319
+
1320
+ private
1321
+
1322
+ def hist(x, nbins = 0)
1323
+ nbins = (3.3 * Math.log10(x.length)).round + 1 if nbins <= 1
1324
+ require 'histogram/array' # dependency
1325
+ x = x.to_a if narray?(x)
1326
+ x, y = x.histogram(nbins, bin_boundary: :min)
1327
+ x.unshift(x.min)
1328
+ [x, y]
1329
+ end
1330
+
1331
+ def barcoordinates(heights, barwidth = 0.8, baseline = 0.0)
1332
+ halfw = barwidth / 2.0
1333
+ wc = []
1334
+ hc = []
1335
+ heights.each_with_index do |value, i|
1336
+ wc << i - halfw
1337
+ wc << i + halfw
1338
+ hc << baseline
1339
+ hc << value
1340
+ end
1341
+ [wc, hc]
1342
+ end
1343
+ end
1344
+ end