gnuplotrb 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,299 +1,299 @@
1
- module GnuplotRB
2
- ##
3
- # Class corresponding to simple 2D visualisation.
4
- #
5
- # == Notebooks
6
- #
7
- # * {Heatmaps}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/heatmaps.ipynb]
8
- # * {Vector field}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/vector_field.ipynb]
9
- # * {Math equations}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/math_plots.ipynb]
10
- # * {Histogram}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/histogram.ipynb]
11
- # * {Updating plots with new data}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/updating_data.ipynb]
12
- #
13
- # == Options
14
- # All possible options are exaplained in
15
- # {gnuplot docs}[http://www.gnuplot.info/docs_5.0/gnuplot.pdf] (pp. 105-190).
16
- #
17
- # Several common ones:
18
- #
19
- # * xrange(yrange, zrange, urange, vrange) - set range for a variable. Takes
20
- # Range (xrange: 0..100), or String (yrange: '[0:100]').
21
- # * title - plot's title. Takes String (title: 'Some new plot').
22
- # * polar (parametric) - plot in polar or parametric space. Takes boolean (true).
23
- # * style_data - set style for plotting data. Takes string, possible values: histogram,
24
- # points, lines, linespoints, boxes etc. See gnuplot docs for more.
25
- # * term - select terminal used by gnuplot. Examples: { term: 'png' },
26
- # { term: ['svg', size: [600, 600]] }. Deprecated due to existance of #to_<term_name> methods.
27
- # One can use #to_png and #to_svg(size: [600, 600]) instead of passing previous options.
28
- # * output - select filename to output plot to. Should be used together with term. Deprecated
29
- # due to existance of #to_<term_name> methods. One should use #to_png('file.png') instead of
30
- # passing { term: 'png', output: 'file.png' }.
31
- # Every option may be passed to constructor in order to create plot with it.
32
- #
33
- # Methods #options(several: options, ...) and bunch of #option_name(only_an: option) such as
34
- # #xrange, #using, #polar etc create new Plot object based on existing but with a new options.
35
- #
36
- # Methods with the same names ending with '!' or '=' ('plot.xrange!(1..3)',
37
- # 'plot.title = "New title"') are destructive and modify state of existing object just as
38
- # "Array#sort!" do with Array object. See notebooks for examples.
39
- class Plot
40
- include Plottable
41
- ##
42
- # Array of datasets which are plotted by this object.
43
- attr_reader :datasets
44
- ##
45
- # @param *datasets [Sequence of Dataset or Array] either instances of Dataset class or
46
- # "[data, **dataset_options]"" arrays
47
- # @param options [Hash] see Plot top level doc for options examples
48
- def initialize(*datasets)
49
- # had to relace **options arg with this because in some cases
50
- # Daru::DataFrame was mentioned as hash and added to options
51
- # instead of plots
52
- @options = Hamster.hash
53
- if datasets[-1].is_a?(Hamster::Hash) || datasets[-1].is_a?(Hash)
54
- @options = Hamster.hash(datasets[-1])
55
- datasets = datasets[0..-2]
56
- end
57
- @datasets = parse_datasets_array(datasets)
58
- @cmd = 'plot '
59
- OptionHandling.validate_terminal_options(@options)
60
- yield(self) if block_given?
61
- end
62
-
63
- ##
64
- # Output plot to term (if given) or to this plot's own terminal.
65
- #
66
- # @param term [Terminal] Terminal object to plot to
67
- # @param :multiplot_part [Boolean] true if this plot is part of a multiplot. For inner use!
68
- # @param options [Hash] see options in Plot top level doc.
69
- # Options passed here have priority over already existing.
70
- # @return [Plot] self
71
- def plot(term = nil, multiplot_part: false, **options)
72
- fail ArgumentError, 'Empty plots are not supported!' if @datasets.empty?
73
- inner_opts = if multiplot_part
74
- @options.merge(options).reject { |key, _| [:term, :output].include?(key) }
75
- else
76
- @options.merge(options)
77
- end
78
- terminal = term || (inner_opts[:output] ? Terminal.new : own_terminal)
79
- ds_string = @datasets.map { |dataset| dataset.to_s(terminal) }.join(' , ')
80
- full_command = @cmd + ds_string
81
- terminal.set(inner_opts).stream_puts(full_command).unset(inner_opts.keys)
82
- if inner_opts[:output]
83
- # guaranteed wait for plotting to finish
84
- terminal.close unless term
85
- # not guaranteed wait for plotting to finish
86
- # work bad with terminals like svg and html
87
- sleep 0.01 until File.size?(inner_opts[:output])
88
- end
89
- self
90
- end
91
-
92
- alias_method :replot, :plot
93
-
94
- ##
95
- # Create new Plot object where dataset at *position* will
96
- # be replaced with the new one created from it by updating.
97
- #
98
- # @param position [Integer] position of dataset which you need to update
99
- # (by default first dataset is updated)
100
- # @param data [#to_gnuplot_points] data to update dataset with
101
- # @param options [Hash] options to update dataset with, see Dataset top level doc
102
- #
103
- # @example
104
- # updated_plot = plot.update_dataset(data: [x1,y1], title: 'After update')
105
- # # plot IS NOT affected (if dataset did not store data in a file)
106
- def update_dataset(position = 0, data: nil, **options)
107
- old_ds = @datasets[position]
108
- new_ds = old_ds.update(data, options)
109
- new_ds.equal?(old_ds) ? self : replace_dataset(position, new_ds)
110
- end
111
-
112
- ##
113
- # Updates existing Plot object by replacing dataset at *position*
114
- # with the new one created from it by updating.
115
- #
116
- # @param position [Integer] position of dataset which you need to update
117
- # (by default first dataset is updated)
118
- # @param data [#to_gnuplot_points] data to update dataset with
119
- # @param options [Hash] options to update dataset with, see Dataset top level doc
120
- #
121
- # @example
122
- # plot.update_dataset!(data: [x1,y1], title: 'After update')
123
- # # plot IS affected anyway
124
- def update_dataset!(position = 0, data: nil, **options)
125
- @datasets[position].update!(data, options)
126
- self
127
- end
128
-
129
- ##
130
- # Create new Plot object where dataset at *position* will
131
- # be replaced with the given one.
132
- #
133
- # @param position [Integer] position of dataset which you need to replace
134
- # (by default first dataset is replaced)
135
- # @param dataset [Dataset, Array] dataset to replace the old one. You can also
136
- # give here "[data, **dataset_options]"" array from which Dataset may be created.
137
- # @example
138
- # sinx = Plot.new('sin(x)')
139
- # cosx = sinx.replace_dataset(['cos(x)'])
140
- # # sinx IS NOT affected
141
- def replace_dataset(position = 0, dataset)
142
- self.class.new(@datasets.set(position, dataset_from_any(dataset)), @options)
143
- end
144
-
145
- ##
146
- # Updates existing Plot object by replacing dataset at *position*
147
- # with the given one.
148
- #
149
- # @param position [Integer] position of dataset which you need to replace
150
- # (by default first dataset is replaced)
151
- # @param dataset [Dataset, Array] dataset to replace the old one. You can also
152
- # give here "[data, **dataset_options]"" array from which Dataset may be created.
153
- # @example
154
- # sinx = Plot.new('sin(x)')
155
- # sinx.replace_dataset!(['cos(x)'])
156
- # # sinx IS affected
157
- def replace_dataset!(position = 0, dataset)
158
- @datasets = @datasets.set(position, dataset_from_any(dataset))
159
- self
160
- end
161
-
162
- alias_method :[]=, :replace_dataset!
163
-
164
- ##
165
- # Create new Plot object where given datasets will
166
- # be inserted into dataset list before given position
167
- # (position = 0 by default).
168
- #
169
- # @param position [Integer] position of dataset BEFORE which datasets will be placed.
170
- # 0 by default.
171
- # @param *datasets [ Sequence of Dataset or Array] datasets to insert
172
- # @example
173
- # sinx = Plot.new('sin(x)')
174
- # sinx_and_cosx_with_expx = sinx.add(['cos(x)'], ['exp(x)'])
175
- #
176
- # cosx_and_sinx = sinx << ['cos(x)']
177
- # # sinx IS NOT affected in both cases
178
- def add_datasets(*datasets)
179
- datasets.map! { |ds| ds.is_a?(Numeric) ? ds : dataset_from_any(ds) }
180
- # first element is position where to add datasets
181
- datasets.unshift(0) unless datasets[0].is_a?(Numeric)
182
- self.class.new(@datasets.insert(*datasets), @options)
183
- end
184
-
185
- alias_method :add_dataset, :add_datasets
186
- alias_method :<<, :add_datasets
187
-
188
- ##
189
- # Updates existing Plot object by inserting given datasets
190
- # into dataset list before given position (position = 0 by default).
191
- #
192
- # @param position [Integer] position of dataset BEFORE which datasets will be placed.
193
- # 0 by default.
194
- # @param *datasets [ Sequence of Dataset or Array] datasets to insert
195
- # @example
196
- # sinx = Plot.new('sin(x)')
197
- # sinx.add!(['cos(x)'], ['exp(x)'])
198
- # # sinx IS affected
199
- def add_datasets!(*datasets)
200
- datasets.map! { |ds| ds.is_a?(Numeric) ? ds : dataset_from_any(ds) }
201
- # first element is position where to add datasets
202
- datasets.unshift(0) unless datasets[0].is_a?(Numeric)
203
- @datasets = @datasets.insert(*datasets)
204
- self
205
- end
206
-
207
- alias_method :add_dataset!, :add_datasets!
208
-
209
- ##
210
- # Create new Plot object where dataset at given position
211
- # will be removed from dataset list.
212
- #
213
- # @param position [Integer] position of dataset that should be
214
- # removed (by default last dataset is removed)
215
- # @example
216
- # sinx_and_cosx = Plot.new('sin(x)', 'cos(x)')
217
- # sinx = sinx_and_cosx.remove_dataset
218
- # cosx = sinx_and_cosx.remove_dataset(0)
219
- # # sinx_and_cosx IS NOT affected in both cases
220
- def remove_dataset(position = -1)
221
- self.class.new(@datasets.delete_at(position), @options)
222
- end
223
-
224
- ##
225
- # Updates existing Plot object by removing dataset at given position.
226
- #
227
- # @param position [Integer] position of dataset that should be
228
- # removed (by default last dataset is removed)
229
- # @example
230
- # sinx_and_cosx = Plot.new('sin(x)', 'cos(x)')
231
- # sinx_and_cosx!.remove_dataset
232
- # sinx_and_cosx!.remove_dataset
233
- # # sinx_and_cosx IS affected and now is empty
234
- def remove_dataset!(position = -1)
235
- @datasets = @datasets.delete_at(position)
236
- self
237
- end
238
-
239
- ##
240
- # The same as #datasets[*args]
241
- def [](*args)
242
- @datasets[*args]
243
- end
244
-
245
- private
246
-
247
- ##
248
- # Checks several conditions and set options needed
249
- # to handle DateTime indexes properly.
250
- def provide_with_datetime_format(data, using)
251
- return unless defined?(Daru)
252
- return unless data.is_a?(Daru::DataFrame) || data.is_a?(Daru::Vector)
253
- return unless data.index.first.is_a?(DateTime)
254
- return if using[0..1] != '1:'
255
- @options = Hamster::Hash.new(
256
- xdata: 'time',
257
- timefmt: '%Y-%m-%dT%H:%M:%S',
258
- format_x: '%d\n%b\n%Y'
259
- ).merge(@options)
260
- end
261
-
262
- ##
263
- # Check if given args is a dataset and returns it. Creates
264
- # new dataset from given args otherwise.
265
- def dataset_from_any(source)
266
- ds = case source
267
- # when initialized with dataframe (it passes here several vectors)
268
- when (defined?(Daru) ? Daru::Vector : nil)
269
- Dataset.new(source)
270
- when Dataset
271
- source.clone
272
- else
273
- Dataset.new(*source)
274
- end
275
- data = source.is_a?(Array) ? source[0] : source
276
- provide_with_datetime_format(data, ds.using)
277
- ds
278
- end
279
-
280
- ##
281
- # Parses given array and returns Hamster::Vector of Datasets
282
- def parse_datasets_array(datasets)
283
- case datasets[0]
284
- when Hamster::Vector
285
- datasets[0]
286
- when (defined?(Daru) ? Daru::DataFrame : nil)
287
- Hamster::Vector.new(datasets[0].map { |ds| dataset_from_any(ds) })
288
- else
289
- Hamster::Vector.new(datasets.map { |ds| dataset_from_any(ds) })
290
- end
291
- end
292
-
293
- ##
294
- # Creates new Plot with existing data and given options.
295
- def new_with_options(options)
296
- self.class.new(@datasets, options)
297
- end
298
- end
299
- end
1
+ module GnuplotRB
2
+ ##
3
+ # Class corresponding to simple 2D visualisation.
4
+ #
5
+ # == Notebooks
6
+ #
7
+ # * {Heatmaps}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/heatmaps.ipynb]
8
+ # * {Vector field}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/vector_field.ipynb]
9
+ # * {Math equations}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/math_plots.ipynb]
10
+ # * {Histogram}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/histogram.ipynb]
11
+ # * {Updating plots with new data}[http://nbviewer.ipython.org/github/dilcom/gnuplotrb/blob/master/notebooks/updating_data.ipynb]
12
+ #
13
+ # == Options
14
+ # All possible options are exaplained in
15
+ # {gnuplot docs}[http://www.gnuplot.info/docs_5.0/gnuplot.pdf] (pp. 105-190).
16
+ #
17
+ # Several common ones:
18
+ #
19
+ # * xrange(yrange, zrange, urange, vrange) - set range for a variable. Takes
20
+ # Range (xrange: 0..100), or String (yrange: '[0:100]').
21
+ # * title - plot's title. Takes String (title: 'Some new plot').
22
+ # * polar (parametric) - plot in polar or parametric space. Takes boolean (true).
23
+ # * style_data - set style for plotting data. Takes string, possible values: histogram,
24
+ # points, lines, linespoints, boxes etc. See gnuplot docs for more.
25
+ # * term - select terminal used by gnuplot. Examples: { term: 'png' },
26
+ # { term: ['svg', size: [600, 600]] }. Deprecated due to existance of #to_<term_name> methods.
27
+ # One can use #to_png and #to_svg(size: [600, 600]) instead of passing previous options.
28
+ # * output - select filename to output plot to. Should be used together with term. Deprecated
29
+ # due to existance of #to_<term_name> methods. One should use #to_png('file.png') instead of
30
+ # passing { term: 'png', output: 'file.png' }.
31
+ # Every option may be passed to constructor in order to create plot with it.
32
+ #
33
+ # Methods #options(several: options, ...) and bunch of #option_name(only_an: option) such as
34
+ # #xrange, #using, #polar etc create new Plot object based on existing but with a new options.
35
+ #
36
+ # Methods with the same names ending with '!' or '=' ('plot.xrange!(1..3)',
37
+ # 'plot.title = "New title"') are destructive and modify state of existing object just as
38
+ # "Array#sort!" do with Array object. See notebooks for examples.
39
+ class Plot
40
+ include Plottable
41
+ ##
42
+ # Array of datasets which are plotted by this object.
43
+ attr_reader :datasets
44
+ ##
45
+ # @param *datasets [Sequence of Dataset or Array] either instances of Dataset class or
46
+ # "[data, **dataset_options]"" arrays
47
+ # @param options [Hash] see Plot top level doc for options examples
48
+ def initialize(*datasets)
49
+ # had to relace **options arg with this because in some cases
50
+ # Daru::DataFrame was mentioned as hash and added to options
51
+ # instead of plots
52
+ @options = Hamster.hash
53
+ if datasets[-1].is_a?(Hamster::Hash) || datasets[-1].is_a?(Hash)
54
+ @options = Hamster.hash(datasets[-1])
55
+ datasets = datasets[0..-2]
56
+ end
57
+ @datasets = parse_datasets_array(datasets)
58
+ @cmd = 'plot '
59
+ OptionHandling.validate_terminal_options(@options)
60
+ yield(self) if block_given?
61
+ end
62
+
63
+ ##
64
+ # Output plot to term (if given) or to this plot's own terminal.
65
+ #
66
+ # @param term [Terminal] Terminal object to plot to
67
+ # @param :multiplot_part [Boolean] true if this plot is part of a multiplot. For inner use!
68
+ # @param options [Hash] see options in Plot top level doc.
69
+ # Options passed here have priority over already existing.
70
+ # @return [Plot] self
71
+ def plot(term = nil, multiplot_part: false, **options)
72
+ fail ArgumentError, 'Empty plots are not supported!' if @datasets.empty?
73
+ inner_opts = if multiplot_part
74
+ @options.merge(options).reject { |key, _| [:term, :output].include?(key) }
75
+ else
76
+ @options.merge(options)
77
+ end
78
+ terminal = term || (inner_opts[:output] ? Terminal.new : own_terminal)
79
+ ds_string = @datasets.map { |dataset| dataset.to_s(terminal) }.join(' , ')
80
+ full_command = @cmd + ds_string
81
+ terminal.set(inner_opts).stream_puts(full_command).unset(inner_opts.keys)
82
+ if inner_opts[:output]
83
+ # guaranteed wait for plotting to finish
84
+ terminal.close unless term
85
+ # not guaranteed wait for plotting to finish
86
+ # work bad with terminals like svg and html
87
+ sleep 0.01 until File.size?(inner_opts[:output])
88
+ end
89
+ self
90
+ end
91
+
92
+ alias_method :replot, :plot
93
+
94
+ ##
95
+ # Create new Plot object where dataset at *position* will
96
+ # be replaced with the new one created from it by updating.
97
+ #
98
+ # @param position [Integer] position of dataset which you need to update
99
+ # (by default first dataset is updated)
100
+ # @param data [#to_gnuplot_points] data to update dataset with
101
+ # @param options [Hash] options to update dataset with, see Dataset top level doc
102
+ #
103
+ # @example
104
+ # updated_plot = plot.update_dataset(data: [x1,y1], title: 'After update')
105
+ # # plot IS NOT affected (if dataset did not store data in a file)
106
+ def update_dataset(position = 0, data: nil, **options)
107
+ old_ds = @datasets[position]
108
+ new_ds = old_ds.update(data, options)
109
+ new_ds.equal?(old_ds) ? self : replace_dataset(position, new_ds)
110
+ end
111
+
112
+ ##
113
+ # Updates existing Plot object by replacing dataset at *position*
114
+ # with the new one created from it by updating.
115
+ #
116
+ # @param position [Integer] position of dataset which you need to update
117
+ # (by default first dataset is updated)
118
+ # @param data [#to_gnuplot_points] data to update dataset with
119
+ # @param options [Hash] options to update dataset with, see Dataset top level doc
120
+ #
121
+ # @example
122
+ # plot.update_dataset!(data: [x1,y1], title: 'After update')
123
+ # # plot IS affected anyway
124
+ def update_dataset!(position = 0, data: nil, **options)
125
+ @datasets[position].update!(data, options)
126
+ self
127
+ end
128
+
129
+ ##
130
+ # Create new Plot object where dataset at *position* will
131
+ # be replaced with the given one.
132
+ #
133
+ # @param position [Integer] position of dataset which you need to replace
134
+ # (by default first dataset is replaced)
135
+ # @param dataset [Dataset, Array] dataset to replace the old one. You can also
136
+ # give here "[data, **dataset_options]"" array from which Dataset may be created.
137
+ # @example
138
+ # sinx = Plot.new('sin(x)')
139
+ # cosx = sinx.replace_dataset(['cos(x)'])
140
+ # # sinx IS NOT affected
141
+ def replace_dataset(position = 0, dataset)
142
+ self.class.new(@datasets.set(position, dataset_from_any(dataset)), @options)
143
+ end
144
+
145
+ ##
146
+ # Updates existing Plot object by replacing dataset at *position*
147
+ # with the given one.
148
+ #
149
+ # @param position [Integer] position of dataset which you need to replace
150
+ # (by default first dataset is replaced)
151
+ # @param dataset [Dataset, Array] dataset to replace the old one. You can also
152
+ # give here "[data, **dataset_options]"" array from which Dataset may be created.
153
+ # @example
154
+ # sinx = Plot.new('sin(x)')
155
+ # sinx.replace_dataset!(['cos(x)'])
156
+ # # sinx IS affected
157
+ def replace_dataset!(position = 0, dataset)
158
+ @datasets = @datasets.set(position, dataset_from_any(dataset))
159
+ self
160
+ end
161
+
162
+ alias_method :[]=, :replace_dataset!
163
+
164
+ ##
165
+ # Create new Plot object where given datasets will
166
+ # be inserted into dataset list before given position
167
+ # (position = 0 by default).
168
+ #
169
+ # @param position [Integer] position of dataset BEFORE which datasets will be placed.
170
+ # 0 by default.
171
+ # @param *datasets [ Sequence of Dataset or Array] datasets to insert
172
+ # @example
173
+ # sinx = Plot.new('sin(x)')
174
+ # sinx_and_cosx_with_expx = sinx.add(['cos(x)'], ['exp(x)'])
175
+ #
176
+ # cosx_and_sinx = sinx << ['cos(x)']
177
+ # # sinx IS NOT affected in both cases
178
+ def add_datasets(*datasets)
179
+ datasets.map! { |ds| ds.is_a?(Numeric) ? ds : dataset_from_any(ds) }
180
+ # first element is position where to add datasets
181
+ datasets.unshift(0) unless datasets[0].is_a?(Numeric)
182
+ self.class.new(@datasets.insert(*datasets), @options)
183
+ end
184
+
185
+ alias_method :add_dataset, :add_datasets
186
+ alias_method :<<, :add_datasets
187
+
188
+ ##
189
+ # Updates existing Plot object by inserting given datasets
190
+ # into dataset list before given position (position = 0 by default).
191
+ #
192
+ # @param position [Integer] position of dataset BEFORE which datasets will be placed.
193
+ # 0 by default.
194
+ # @param *datasets [ Sequence of Dataset or Array] datasets to insert
195
+ # @example
196
+ # sinx = Plot.new('sin(x)')
197
+ # sinx.add!(['cos(x)'], ['exp(x)'])
198
+ # # sinx IS affected
199
+ def add_datasets!(*datasets)
200
+ datasets.map! { |ds| ds.is_a?(Numeric) ? ds : dataset_from_any(ds) }
201
+ # first element is position where to add datasets
202
+ datasets.unshift(0) unless datasets[0].is_a?(Numeric)
203
+ @datasets = @datasets.insert(*datasets)
204
+ self
205
+ end
206
+
207
+ alias_method :add_dataset!, :add_datasets!
208
+
209
+ ##
210
+ # Create new Plot object where dataset at given position
211
+ # will be removed from dataset list.
212
+ #
213
+ # @param position [Integer] position of dataset that should be
214
+ # removed (by default last dataset is removed)
215
+ # @example
216
+ # sinx_and_cosx = Plot.new('sin(x)', 'cos(x)')
217
+ # sinx = sinx_and_cosx.remove_dataset
218
+ # cosx = sinx_and_cosx.remove_dataset(0)
219
+ # # sinx_and_cosx IS NOT affected in both cases
220
+ def remove_dataset(position = -1)
221
+ self.class.new(@datasets.delete_at(position), @options)
222
+ end
223
+
224
+ ##
225
+ # Updates existing Plot object by removing dataset at given position.
226
+ #
227
+ # @param position [Integer] position of dataset that should be
228
+ # removed (by default last dataset is removed)
229
+ # @example
230
+ # sinx_and_cosx = Plot.new('sin(x)', 'cos(x)')
231
+ # sinx_and_cosx!.remove_dataset
232
+ # sinx_and_cosx!.remove_dataset
233
+ # # sinx_and_cosx IS affected and now is empty
234
+ def remove_dataset!(position = -1)
235
+ @datasets = @datasets.delete_at(position)
236
+ self
237
+ end
238
+
239
+ ##
240
+ # The same as #datasets[*args]
241
+ def [](*args)
242
+ @datasets[*args]
243
+ end
244
+
245
+ private
246
+
247
+ ##
248
+ # Checks several conditions and set options needed
249
+ # to handle DateTime indexes properly.
250
+ def provide_with_datetime_format(data, using)
251
+ return unless defined?(Daru)
252
+ return unless data.is_a?(Daru::DataFrame) || data.is_a?(Daru::Vector)
253
+ return unless data.index.first.is_a?(DateTime)
254
+ return if using[0..1] != '1:'
255
+ @options = Hamster::Hash.new(
256
+ xdata: 'time',
257
+ timefmt: '%Y-%m-%dT%H:%M:%S',
258
+ format_x: '%d\n%b\n%Y'
259
+ ).merge(@options)
260
+ end
261
+
262
+ ##
263
+ # Check if given args is a dataset and returns it. Creates
264
+ # new dataset from given args otherwise.
265
+ def dataset_from_any(source)
266
+ ds = case source
267
+ # when initialized with dataframe (it passes here several vectors)
268
+ when (defined?(Daru) ? Daru::Vector : nil)
269
+ Dataset.new(source)
270
+ when Dataset
271
+ source.clone
272
+ else
273
+ Dataset.new(*source)
274
+ end
275
+ data = source.is_a?(Array) ? source[0] : source
276
+ provide_with_datetime_format(data, ds.using)
277
+ ds
278
+ end
279
+
280
+ ##
281
+ # Parses given array and returns Hamster::Vector of Datasets
282
+ def parse_datasets_array(datasets)
283
+ case datasets[0]
284
+ when Hamster::Vector
285
+ datasets[0]
286
+ when (defined?(Daru) ? Daru::DataFrame : nil)
287
+ Hamster::Vector.new(datasets[0].map { |ds| dataset_from_any(ds) })
288
+ else
289
+ Hamster::Vector.new(datasets.map { |ds| dataset_from_any(ds) })
290
+ end
291
+ end
292
+
293
+ ##
294
+ # Creates new Plot with existing data and given options.
295
+ def new_with_options(options)
296
+ self.class.new(@datasets, options)
297
+ end
298
+ end
299
+ end