gnuplotrb 0.3.1 → 0.3.2
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.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/LICENSE +20 -20
- data/README.rdoc +163 -163
- data/Rakefile +16 -16
- data/gnuplotrb.gemspec +30 -30
- data/lib/gnuplotrb.rb +35 -35
- data/lib/gnuplotrb/animation.rb +129 -129
- data/lib/gnuplotrb/external_classes/array.rb +17 -17
- data/lib/gnuplotrb/external_classes/daru.rb +43 -43
- data/lib/gnuplotrb/external_classes/string.rb +6 -6
- data/lib/gnuplotrb/fit.rb +204 -204
- data/lib/gnuplotrb/mixins/error_handling.rb +48 -48
- data/lib/gnuplotrb/mixins/option_handling.rb +190 -190
- data/lib/gnuplotrb/mixins/plottable.rb +208 -208
- data/lib/gnuplotrb/multiplot.rb +269 -269
- data/lib/gnuplotrb/plot.rb +299 -299
- data/lib/gnuplotrb/splot.rb +18 -18
- data/lib/gnuplotrb/staff/datablock.rb +112 -112
- data/lib/gnuplotrb/staff/dataset.rb +294 -294
- data/lib/gnuplotrb/staff/settings.rb +89 -80
- data/lib/gnuplotrb/staff/terminal.rb +202 -202
- data/lib/gnuplotrb/version.rb +8 -8
- metadata +3 -4
data/lib/gnuplotrb/multiplot.rb
CHANGED
@@ -1,269 +1,269 @@
|
|
1
|
-
module GnuplotRB
|
2
|
-
##
|
3
|
-
# Multiplot allows to place several plots on one layout.
|
4
|
-
# It's usage is covered in
|
5
|
-
# {multiplot notebook}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/multiplot_layout.ipynb].
|
6
|
-
#
|
7
|
-
# == Options
|
8
|
-
# Most of Multiplot options are the same as in Plot so one can also set any options related
|
9
|
-
# to Plot and they will be considered by all nested plots
|
10
|
-
# (if they does not override it with their own values).
|
11
|
-
#
|
12
|
-
# There are only 2 specific options:
|
13
|
-
# * title - set title for the whole layout (above all the plots)
|
14
|
-
# * layout - set layout size, examples:
|
15
|
-
# { layout : [1, 3] } # 3 plots, 1 row, 3 columns
|
16
|
-
# { layout : [2, 2] } # 4 plots, 2 rows, 2 columns
|
17
|
-
class Multiplot
|
18
|
-
include Plottable
|
19
|
-
##
|
20
|
-
# @return [Array] Array of plots contained by this object
|
21
|
-
attr_reader :plots
|
22
|
-
|
23
|
-
##
|
24
|
-
# @param plots [Plot, Splot, Hamster::Vector] Hamster vector (or just sequence) with Plot
|
25
|
-
# or Splot objects which should be placed on this multiplot layout
|
26
|
-
# @param options [Hash] see options in top class docs
|
27
|
-
def initialize(*plots, **options)
|
28
|
-
@plots = plots[0].is_a?(Hamster::Vector) ? plots[0] : Hamster::Vector.new(plots)
|
29
|
-
@options = Hamster.hash(options)
|
30
|
-
OptionHandling.validate_terminal_options(@options)
|
31
|
-
yield(self) if block_given?
|
32
|
-
end
|
33
|
-
|
34
|
-
##
|
35
|
-
# Output all the plots to term (if given) or to this Multiplot's own terminal.
|
36
|
-
#
|
37
|
-
# @param term [Terminal] Terminal to plot to
|
38
|
-
# @param multiplot_part [Boolean] placeholder, does not really needed and should not be used
|
39
|
-
# @param options [Hash] see options in top class docs.
|
40
|
-
# Options passed here have priority over already set.
|
41
|
-
# @return [Multiplot] self
|
42
|
-
def plot(term = nil, multiplot_part: false, **options)
|
43
|
-
plot_options = mix_options(options) do |plot_opts, mp_opts|
|
44
|
-
plot_opts.merge(multiplot: mp_opts.to_h)
|
45
|
-
end
|
46
|
-
terminal = term || (plot_options[:output] ? Terminal.new : own_terminal)
|
47
|
-
multiplot(terminal, plot_options)
|
48
|
-
if plot_options[:output]
|
49
|
-
# guaranteed wait for plotting to finish
|
50
|
-
terminal.close unless term
|
51
|
-
# not guaranteed wait for plotting to finish
|
52
|
-
# work bad with terminals like svg and html
|
53
|
-
sleep 0.01 until File.size?(plot_options[:output])
|
54
|
-
end
|
55
|
-
self
|
56
|
-
end
|
57
|
-
|
58
|
-
##
|
59
|
-
# Create new updated Multiplot object
|
60
|
-
# where plot (Plot or Splot object) at *position* will
|
61
|
-
# be replaced with the new one created from it by updating.
|
62
|
-
# To update a plot you can pass some options for it or a
|
63
|
-
# block, that should take existing plot (with new options if
|
64
|
-
# you gave them) and return a plot too.
|
65
|
-
#
|
66
|
-
# Method yields new created Plot or Splot to allow you update it manually.
|
67
|
-
#
|
68
|
-
# @param position [Integer] position of plot which you need to update
|
69
|
-
# (by default first plot is updated)
|
70
|
-
# @param options [Hash] options to set into updated plot
|
71
|
-
# @return [Multiplot] self
|
72
|
-
# @yieldparam plot [Plot, Splot] a new plot
|
73
|
-
# @yieldreturn [Plot, Splot] changed plot
|
74
|
-
# @example
|
75
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
76
|
-
# updated_mp = mp.update_plot(title: 'Sin(x) and Exp(x)') { |sinx| sinx.add!('exp(x)') }
|
77
|
-
# # mp IS NOT affected
|
78
|
-
def update_plot(position = 0, **options)
|
79
|
-
return self unless block_given? if options.empty?
|
80
|
-
replacement = @plots[position].options(options)
|
81
|
-
replacement = yield(replacement) if block_given?
|
82
|
-
replace_plot(position, replacement)
|
83
|
-
end
|
84
|
-
|
85
|
-
alias_method :update, :update_plot
|
86
|
-
|
87
|
-
##
|
88
|
-
# Destructive version of #update_plot.
|
89
|
-
#
|
90
|
-
# @return [Multiplot] self
|
91
|
-
# @example
|
92
|
-
# Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
93
|
-
# mp.update_plot!(title: 'Sin(x) and Exp(x)') { |sinx| sinx.add!('exp(x)') }
|
94
|
-
# # mp IS affected
|
95
|
-
def update_plot!(position = 0, **options)
|
96
|
-
return self unless block_given? if options.empty?
|
97
|
-
replacement = @plots[position].options!(options)
|
98
|
-
yield(replacement) if block_given?
|
99
|
-
self
|
100
|
-
end
|
101
|
-
|
102
|
-
alias_method :update!, :update_plot!
|
103
|
-
|
104
|
-
##
|
105
|
-
# Create new Multiplot object where plot (Plot or Splot object)
|
106
|
-
# at *position* will be replaced with the given one.
|
107
|
-
#
|
108
|
-
# @param position [Integer] position of plot which you need to replace
|
109
|
-
# (by default first plot is replace)
|
110
|
-
# @param plot [Plot, Splot] replacement
|
111
|
-
# @return [Multiplot] self
|
112
|
-
# @example
|
113
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
114
|
-
# mp_with_replaced_plot = mp.replace_plot(Plot.new('exp(x)', title: 'exp instead of sin'))
|
115
|
-
# # mp IS NOT affected
|
116
|
-
def replace_plot(position = 0, plot)
|
117
|
-
self.class.new(@plots.set(position, plot), @options)
|
118
|
-
end
|
119
|
-
|
120
|
-
alias_method :replace, :replace_plot
|
121
|
-
|
122
|
-
##
|
123
|
-
# Destructive version of #replace_plot.
|
124
|
-
#
|
125
|
-
# @return [Multiplot] self
|
126
|
-
# @example
|
127
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
128
|
-
# mp.replace_plot!(Plot.new('exp(x)', title: 'exp instead of sin'))
|
129
|
-
# # mp IS affected
|
130
|
-
def replace_plot!(position = 0, plot)
|
131
|
-
@plots = @plots.set(position, plot)
|
132
|
-
self
|
133
|
-
end
|
134
|
-
|
135
|
-
alias_method :replace!, :replace_plot!
|
136
|
-
alias_method :[]=, :replace_plot!
|
137
|
-
|
138
|
-
##
|
139
|
-
# Create new Multiplot with given *plots* added before plot at given *position*.
|
140
|
-
# (by default it adds plot at the front).
|
141
|
-
#
|
142
|
-
# @param position [Integer] position of plot which you need to replace
|
143
|
-
# (by default first plot is replace)
|
144
|
-
# @param plots [Sequence of Plot or Splot] plots you want to add
|
145
|
-
# @return [Multiplot] self
|
146
|
-
# @example
|
147
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
148
|
-
# enlarged_mp = mp.add_plots(Plot.new('exp(x)')).layout([3,1])
|
149
|
-
# # mp IS NOT affected
|
150
|
-
def add_plots(*plots)
|
151
|
-
plots.unshift(0) unless plots[0].is_a?(Numeric)
|
152
|
-
self.class.new(@plots.insert(*plots), @options)
|
153
|
-
end
|
154
|
-
|
155
|
-
alias_method :add_plot, :add_plots
|
156
|
-
alias_method :<<, :add_plots
|
157
|
-
alias_method :add, :add_plots
|
158
|
-
|
159
|
-
##
|
160
|
-
# Destructive version of #add_plots.
|
161
|
-
#
|
162
|
-
# @return [Multiplot] self
|
163
|
-
# @example
|
164
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
165
|
-
# mp.add_plots!(Plot.new('exp(x)')).layout([3,1])
|
166
|
-
# # mp IS affected
|
167
|
-
def add_plots!(*plots)
|
168
|
-
plots.unshift(0) unless plots[0].is_a?(Numeric)
|
169
|
-
@plots = @plots.insert(*plots)
|
170
|
-
self
|
171
|
-
end
|
172
|
-
|
173
|
-
alias_method :add_plot!, :add_plots!
|
174
|
-
alias_method :add!, :add_plots!
|
175
|
-
|
176
|
-
##
|
177
|
-
# Create new Multiplot without plot at given position
|
178
|
-
# (by default last plot is removed).
|
179
|
-
#
|
180
|
-
# @param position [Integer] position of plot which you need to remove
|
181
|
-
# (by default last plot is removed)
|
182
|
-
# @return [Multiplot] self
|
183
|
-
# @example
|
184
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
185
|
-
# mp_with_only_cos = mp.remove_plot(0)
|
186
|
-
# # mp IS NOT affected
|
187
|
-
def remove_plot(position = -1)
|
188
|
-
self.class.new(@plots.delete_at(position), @options)
|
189
|
-
end
|
190
|
-
|
191
|
-
alias_method :remove, :remove_plot
|
192
|
-
|
193
|
-
##
|
194
|
-
# Destructive version of #remove_plot.
|
195
|
-
#
|
196
|
-
# @return [Multiplot] self
|
197
|
-
# @example
|
198
|
-
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
199
|
-
# mp.remove_plot!(0)
|
200
|
-
# # mp IS affected
|
201
|
-
def remove_plot!(position = -1)
|
202
|
-
@plots = @plots.delete_at(position)
|
203
|
-
self
|
204
|
-
end
|
205
|
-
|
206
|
-
alias_method :remove!, :remove_plot!
|
207
|
-
|
208
|
-
##
|
209
|
-
# Equal to #plots[*args]
|
210
|
-
def [](*args)
|
211
|
-
@plots[*args]
|
212
|
-
end
|
213
|
-
|
214
|
-
private
|
215
|
-
|
216
|
-
##
|
217
|
-
# Default options to be used for that plot
|
218
|
-
def default_options
|
219
|
-
{
|
220
|
-
layout: [2, 2],
|
221
|
-
title: 'Multiplot'
|
222
|
-
}
|
223
|
-
end
|
224
|
-
|
225
|
-
##
|
226
|
-
# This plot have some specific options which
|
227
|
-
# should be handled different way than others.
|
228
|
-
# Here are keys of this options.
|
229
|
-
def specific_keys
|
230
|
-
%w(
|
231
|
-
title
|
232
|
-
layout
|
233
|
-
)
|
234
|
-
end
|
235
|
-
|
236
|
-
##
|
237
|
-
# Create new Multiplot object with the same set of plots and
|
238
|
-
# given options.
|
239
|
-
# Used in OptionHandling module.
|
240
|
-
def new_with_options(options)
|
241
|
-
self.class.new(@plots, options)
|
242
|
-
end
|
243
|
-
|
244
|
-
##
|
245
|
-
# Check if given options corresponds to multiplot.
|
246
|
-
# Uses #specific_keys to check.
|
247
|
-
def specific_option?(key)
|
248
|
-
specific_keys.include?(key.to_s)
|
249
|
-
end
|
250
|
-
|
251
|
-
##
|
252
|
-
# Takes all options and splits them into specific and
|
253
|
-
# others. Requires a block where this two classes should
|
254
|
-
# be mixed.
|
255
|
-
def mix_options(options)
|
256
|
-
all_options = @options.merge(options)
|
257
|
-
specific_options, plot_options = all_options.partition { |key, _value| specific_option?(key) }
|
258
|
-
yield(plot_options, default_options.merge(specific_options))
|
259
|
-
end
|
260
|
-
|
261
|
-
##
|
262
|
-
# Just a part of #plot.
|
263
|
-
def multiplot(terminal, options)
|
264
|
-
terminal.set(options)
|
265
|
-
@plots.each { |graph| graph.plot(terminal, multiplot_part: true) }
|
266
|
-
terminal.unset(options.keys)
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
1
|
+
module GnuplotRB
|
2
|
+
##
|
3
|
+
# Multiplot allows to place several plots on one layout.
|
4
|
+
# It's usage is covered in
|
5
|
+
# {multiplot notebook}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/multiplot_layout.ipynb].
|
6
|
+
#
|
7
|
+
# == Options
|
8
|
+
# Most of Multiplot options are the same as in Plot so one can also set any options related
|
9
|
+
# to Plot and they will be considered by all nested plots
|
10
|
+
# (if they does not override it with their own values).
|
11
|
+
#
|
12
|
+
# There are only 2 specific options:
|
13
|
+
# * title - set title for the whole layout (above all the plots)
|
14
|
+
# * layout - set layout size, examples:
|
15
|
+
# { layout : [1, 3] } # 3 plots, 1 row, 3 columns
|
16
|
+
# { layout : [2, 2] } # 4 plots, 2 rows, 2 columns
|
17
|
+
class Multiplot
|
18
|
+
include Plottable
|
19
|
+
##
|
20
|
+
# @return [Array] Array of plots contained by this object
|
21
|
+
attr_reader :plots
|
22
|
+
|
23
|
+
##
|
24
|
+
# @param plots [Plot, Splot, Hamster::Vector] Hamster vector (or just sequence) with Plot
|
25
|
+
# or Splot objects which should be placed on this multiplot layout
|
26
|
+
# @param options [Hash] see options in top class docs
|
27
|
+
def initialize(*plots, **options)
|
28
|
+
@plots = plots[0].is_a?(Hamster::Vector) ? plots[0] : Hamster::Vector.new(plots)
|
29
|
+
@options = Hamster.hash(options)
|
30
|
+
OptionHandling.validate_terminal_options(@options)
|
31
|
+
yield(self) if block_given?
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Output all the plots to term (if given) or to this Multiplot's own terminal.
|
36
|
+
#
|
37
|
+
# @param term [Terminal] Terminal to plot to
|
38
|
+
# @param multiplot_part [Boolean] placeholder, does not really needed and should not be used
|
39
|
+
# @param options [Hash] see options in top class docs.
|
40
|
+
# Options passed here have priority over already set.
|
41
|
+
# @return [Multiplot] self
|
42
|
+
def plot(term = nil, multiplot_part: false, **options)
|
43
|
+
plot_options = mix_options(options) do |plot_opts, mp_opts|
|
44
|
+
plot_opts.merge(multiplot: mp_opts.to_h)
|
45
|
+
end
|
46
|
+
terminal = term || (plot_options[:output] ? Terminal.new : own_terminal)
|
47
|
+
multiplot(terminal, plot_options)
|
48
|
+
if plot_options[:output]
|
49
|
+
# guaranteed wait for plotting to finish
|
50
|
+
terminal.close unless term
|
51
|
+
# not guaranteed wait for plotting to finish
|
52
|
+
# work bad with terminals like svg and html
|
53
|
+
sleep 0.01 until File.size?(plot_options[:output])
|
54
|
+
end
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Create new updated Multiplot object
|
60
|
+
# where plot (Plot or Splot object) at *position* will
|
61
|
+
# be replaced with the new one created from it by updating.
|
62
|
+
# To update a plot you can pass some options for it or a
|
63
|
+
# block, that should take existing plot (with new options if
|
64
|
+
# you gave them) and return a plot too.
|
65
|
+
#
|
66
|
+
# Method yields new created Plot or Splot to allow you update it manually.
|
67
|
+
#
|
68
|
+
# @param position [Integer] position of plot which you need to update
|
69
|
+
# (by default first plot is updated)
|
70
|
+
# @param options [Hash] options to set into updated plot
|
71
|
+
# @return [Multiplot] self
|
72
|
+
# @yieldparam plot [Plot, Splot] a new plot
|
73
|
+
# @yieldreturn [Plot, Splot] changed plot
|
74
|
+
# @example
|
75
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
76
|
+
# updated_mp = mp.update_plot(title: 'Sin(x) and Exp(x)') { |sinx| sinx.add!('exp(x)') }
|
77
|
+
# # mp IS NOT affected
|
78
|
+
def update_plot(position = 0, **options)
|
79
|
+
return self unless block_given? if options.empty?
|
80
|
+
replacement = @plots[position].options(options)
|
81
|
+
replacement = yield(replacement) if block_given?
|
82
|
+
replace_plot(position, replacement)
|
83
|
+
end
|
84
|
+
|
85
|
+
alias_method :update, :update_plot
|
86
|
+
|
87
|
+
##
|
88
|
+
# Destructive version of #update_plot.
|
89
|
+
#
|
90
|
+
# @return [Multiplot] self
|
91
|
+
# @example
|
92
|
+
# Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
93
|
+
# mp.update_plot!(title: 'Sin(x) and Exp(x)') { |sinx| sinx.add!('exp(x)') }
|
94
|
+
# # mp IS affected
|
95
|
+
def update_plot!(position = 0, **options)
|
96
|
+
return self unless block_given? if options.empty?
|
97
|
+
replacement = @plots[position].options!(options)
|
98
|
+
yield(replacement) if block_given?
|
99
|
+
self
|
100
|
+
end
|
101
|
+
|
102
|
+
alias_method :update!, :update_plot!
|
103
|
+
|
104
|
+
##
|
105
|
+
# Create new Multiplot object where plot (Plot or Splot object)
|
106
|
+
# at *position* will be replaced with the given one.
|
107
|
+
#
|
108
|
+
# @param position [Integer] position of plot which you need to replace
|
109
|
+
# (by default first plot is replace)
|
110
|
+
# @param plot [Plot, Splot] replacement
|
111
|
+
# @return [Multiplot] self
|
112
|
+
# @example
|
113
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
114
|
+
# mp_with_replaced_plot = mp.replace_plot(Plot.new('exp(x)', title: 'exp instead of sin'))
|
115
|
+
# # mp IS NOT affected
|
116
|
+
def replace_plot(position = 0, plot)
|
117
|
+
self.class.new(@plots.set(position, plot), @options)
|
118
|
+
end
|
119
|
+
|
120
|
+
alias_method :replace, :replace_plot
|
121
|
+
|
122
|
+
##
|
123
|
+
# Destructive version of #replace_plot.
|
124
|
+
#
|
125
|
+
# @return [Multiplot] self
|
126
|
+
# @example
|
127
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
128
|
+
# mp.replace_plot!(Plot.new('exp(x)', title: 'exp instead of sin'))
|
129
|
+
# # mp IS affected
|
130
|
+
def replace_plot!(position = 0, plot)
|
131
|
+
@plots = @plots.set(position, plot)
|
132
|
+
self
|
133
|
+
end
|
134
|
+
|
135
|
+
alias_method :replace!, :replace_plot!
|
136
|
+
alias_method :[]=, :replace_plot!
|
137
|
+
|
138
|
+
##
|
139
|
+
# Create new Multiplot with given *plots* added before plot at given *position*.
|
140
|
+
# (by default it adds plot at the front).
|
141
|
+
#
|
142
|
+
# @param position [Integer] position of plot which you need to replace
|
143
|
+
# (by default first plot is replace)
|
144
|
+
# @param plots [Sequence of Plot or Splot] plots you want to add
|
145
|
+
# @return [Multiplot] self
|
146
|
+
# @example
|
147
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
148
|
+
# enlarged_mp = mp.add_plots(Plot.new('exp(x)')).layout([3,1])
|
149
|
+
# # mp IS NOT affected
|
150
|
+
def add_plots(*plots)
|
151
|
+
plots.unshift(0) unless plots[0].is_a?(Numeric)
|
152
|
+
self.class.new(@plots.insert(*plots), @options)
|
153
|
+
end
|
154
|
+
|
155
|
+
alias_method :add_plot, :add_plots
|
156
|
+
alias_method :<<, :add_plots
|
157
|
+
alias_method :add, :add_plots
|
158
|
+
|
159
|
+
##
|
160
|
+
# Destructive version of #add_plots.
|
161
|
+
#
|
162
|
+
# @return [Multiplot] self
|
163
|
+
# @example
|
164
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
165
|
+
# mp.add_plots!(Plot.new('exp(x)')).layout([3,1])
|
166
|
+
# # mp IS affected
|
167
|
+
def add_plots!(*plots)
|
168
|
+
plots.unshift(0) unless plots[0].is_a?(Numeric)
|
169
|
+
@plots = @plots.insert(*plots)
|
170
|
+
self
|
171
|
+
end
|
172
|
+
|
173
|
+
alias_method :add_plot!, :add_plots!
|
174
|
+
alias_method :add!, :add_plots!
|
175
|
+
|
176
|
+
##
|
177
|
+
# Create new Multiplot without plot at given position
|
178
|
+
# (by default last plot is removed).
|
179
|
+
#
|
180
|
+
# @param position [Integer] position of plot which you need to remove
|
181
|
+
# (by default last plot is removed)
|
182
|
+
# @return [Multiplot] self
|
183
|
+
# @example
|
184
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
185
|
+
# mp_with_only_cos = mp.remove_plot(0)
|
186
|
+
# # mp IS NOT affected
|
187
|
+
def remove_plot(position = -1)
|
188
|
+
self.class.new(@plots.delete_at(position), @options)
|
189
|
+
end
|
190
|
+
|
191
|
+
alias_method :remove, :remove_plot
|
192
|
+
|
193
|
+
##
|
194
|
+
# Destructive version of #remove_plot.
|
195
|
+
#
|
196
|
+
# @return [Multiplot] self
|
197
|
+
# @example
|
198
|
+
# mp = Multiplot.new(Plot.new('sin(x)'), Plot.new('cos(x)'), layout: [2,1])
|
199
|
+
# mp.remove_plot!(0)
|
200
|
+
# # mp IS affected
|
201
|
+
def remove_plot!(position = -1)
|
202
|
+
@plots = @plots.delete_at(position)
|
203
|
+
self
|
204
|
+
end
|
205
|
+
|
206
|
+
alias_method :remove!, :remove_plot!
|
207
|
+
|
208
|
+
##
|
209
|
+
# Equal to #plots[*args]
|
210
|
+
def [](*args)
|
211
|
+
@plots[*args]
|
212
|
+
end
|
213
|
+
|
214
|
+
private
|
215
|
+
|
216
|
+
##
|
217
|
+
# Default options to be used for that plot
|
218
|
+
def default_options
|
219
|
+
{
|
220
|
+
layout: [2, 2],
|
221
|
+
title: 'Multiplot'
|
222
|
+
}
|
223
|
+
end
|
224
|
+
|
225
|
+
##
|
226
|
+
# This plot have some specific options which
|
227
|
+
# should be handled different way than others.
|
228
|
+
# Here are keys of this options.
|
229
|
+
def specific_keys
|
230
|
+
%w(
|
231
|
+
title
|
232
|
+
layout
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
##
|
237
|
+
# Create new Multiplot object with the same set of plots and
|
238
|
+
# given options.
|
239
|
+
# Used in OptionHandling module.
|
240
|
+
def new_with_options(options)
|
241
|
+
self.class.new(@plots, options)
|
242
|
+
end
|
243
|
+
|
244
|
+
##
|
245
|
+
# Check if given options corresponds to multiplot.
|
246
|
+
# Uses #specific_keys to check.
|
247
|
+
def specific_option?(key)
|
248
|
+
specific_keys.include?(key.to_s)
|
249
|
+
end
|
250
|
+
|
251
|
+
##
|
252
|
+
# Takes all options and splits them into specific and
|
253
|
+
# others. Requires a block where this two classes should
|
254
|
+
# be mixed.
|
255
|
+
def mix_options(options)
|
256
|
+
all_options = @options.merge(options)
|
257
|
+
specific_options, plot_options = all_options.partition { |key, _value| specific_option?(key) }
|
258
|
+
yield(plot_options, default_options.merge(specific_options))
|
259
|
+
end
|
260
|
+
|
261
|
+
##
|
262
|
+
# Just a part of #plot.
|
263
|
+
def multiplot(terminal, options)
|
264
|
+
terminal.set(options)
|
265
|
+
@plots.each { |graph| graph.plot(terminal, multiplot_part: true) }
|
266
|
+
terminal.unset(options.keys)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|