ruby-gr 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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