technical_graph 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/DOCUMENTATION.textile +374 -0
- data/README.md +35 -96
- data/VERSION +1 -1
- data/lib/technical_graph/array.rb +14 -0
- data/lib/technical_graph/data_layer.rb +42 -34
- data/lib/technical_graph/data_layer_processor.rb +24 -194
- data/lib/technical_graph/data_layer_processor_noise_removal.rb +90 -0
- data/lib/technical_graph/data_layer_processor_simple_smoother.rb +234 -0
- data/lib/technical_graph/data_point.rb +43 -0
- data/lib/technical_graph/graph_axis.rb +18 -6
- data/lib/technical_graph/graph_image_drawer.rb +8 -6
- data/lib/technical_graph.rb +0 -2
- data/test/test_technical_autocolor.rb +2 -1
- data/test/test_technical_axis_enlarge.rb +2 -1
- data/test/test_technical_graph.rb +20 -10
- data/test/test_technical_graph_axis.rb +12 -6
- data/test/test_technical_multilayer.rb +2 -1
- data/test/test_technical_noise_removal.rb +36 -0
- data/test/test_technical_readme.rb +207 -0
- data/test/test_technical_simple_graph.rb +2 -1
- data/test/test_technical_smoother.rb +18 -18
- data/test/test_technical_smoother_adv.rb +115 -0
- metadata +12 -4
@@ -0,0 +1,374 @@
|
|
1
|
+
h1. How to use it
|
2
|
+
|
3
|
+
p. All this examples are generated in test/test_technical_readme.rb.
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
h2. Simple graph
|
10
|
+
|
11
|
+
p. First thing we need to have data to show on graph, for example something like:
|
12
|
+
|
13
|
+
<pre>
|
14
|
+
<code>
|
15
|
+
@simple_data_array = [
|
16
|
+
{ :x => 0, :y => 0 },
|
17
|
+
{ :x => 1, :y => 1 },
|
18
|
+
{ :x => 2, :y => 2 },
|
19
|
+
{ :x => 3, :y => 2 },
|
20
|
+
{ :x => 4, :y => 1 },
|
21
|
+
{ :x => 5, :y => 0 },
|
22
|
+
]
|
23
|
+
</code>
|
24
|
+
</pre>
|
25
|
+
|
26
|
+
p. If you want to put this data on graph you need to create TechnicalGraph object
|
27
|
+
|
28
|
+
<pre>
|
29
|
+
<code>
|
30
|
+
@tg = TechnicalGraph.new
|
31
|
+
</code>
|
32
|
+
</pre>
|
33
|
+
|
34
|
+
p. and add a layer.
|
35
|
+
|
36
|
+
<pre>
|
37
|
+
<code>
|
38
|
+
@tg.add_layer(@simple_data_array)
|
39
|
+
</code>
|
40
|
+
</pre>
|
41
|
+
|
42
|
+
p. We added data but we don't see anything. Now we have to render graph and save it to file.
|
43
|
+
|
44
|
+
<pre>
|
45
|
+
<code>
|
46
|
+
@tg.render
|
47
|
+
file_name = 'samples/readme/01_simplest.png'
|
48
|
+
@tg.image_drawer.save_to_file(file_name)
|
49
|
+
</code>
|
50
|
+
</pre>
|
51
|
+
|
52
|
+
p. And we got our first graph with one layer without any options changes, a bit raw.
|
53
|
+
|
54
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/01_simplest.png((01) simple graph)!
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
h2. More layers
|
61
|
+
|
62
|
+
p. Maybe example with two layers?
|
63
|
+
|
64
|
+
<pre>
|
65
|
+
<code>
|
66
|
+
@simple_data_array = [
|
67
|
+
{ :x => 0, :y => 0 },
|
68
|
+
{ :x => 1, :y => 1 },
|
69
|
+
{ :x => 2, :y => 2 },
|
70
|
+
{ :x => 3, :y => 2 },
|
71
|
+
{ :x => 4, :y => 1 },
|
72
|
+
{ :x => 5, :y => 0 },
|
73
|
+
]
|
74
|
+
|
75
|
+
@simple_data_array_b = [
|
76
|
+
{ :x => 0.5, :y => 0.5 },
|
77
|
+
{ :x => 1.5, :y => 0.5 },
|
78
|
+
{ :x => 2.5, :y => 1.5 },
|
79
|
+
{ :x => 3.5, :y => 1.0 },
|
80
|
+
{ :x => 4.5, :y => 1.5 },
|
81
|
+
{ :x => 5.5, :y => 1.5 },
|
82
|
+
]
|
83
|
+
|
84
|
+
@tg = TechnicalGraph.new
|
85
|
+
@tg.add_layer(@simple_data_array)
|
86
|
+
@tg.add_layer(@simple_data_array_b)
|
87
|
+
@tg.render
|
88
|
+
file_name = 'samples/readme/02_two_layers.png'
|
89
|
+
@tg.image_drawer.save_to_file(file_name)
|
90
|
+
</code>
|
91
|
+
</pre>
|
92
|
+
|
93
|
+
|
94
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/02_two_layers.png((02) simple graph)!
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
h2. Ranges
|
100
|
+
|
101
|
+
p. On default ranges are calculated automatically so all points are visible. You can override ranges setting.
|
102
|
+
|
103
|
+
<pre>
|
104
|
+
<code>
|
105
|
+
@simple_data_array = [
|
106
|
+
{ :x => 0, :y => 0 },
|
107
|
+
{ :x => 1, :y => 1 },
|
108
|
+
{ :x => 2, :y => 2 },
|
109
|
+
{ :x => 3, :y => 2 },
|
110
|
+
{ :x => 4, :y => 1 },
|
111
|
+
{ :x => 5, :y => 0 },
|
112
|
+
]
|
113
|
+
|
114
|
+
@tg = TechnicalGraph.new(
|
115
|
+
{
|
116
|
+
:x_min => -2,
|
117
|
+
:x_max => 10,
|
118
|
+
:y_min => -1,
|
119
|
+
:y_max => 10,
|
120
|
+
})
|
121
|
+
|
122
|
+
@tg.add_layer(@simple_data_array)
|
123
|
+
@tg.render
|
124
|
+
file_name = 'samples/readme/03_changed_ranges.png'
|
125
|
+
@tg.image_drawer.save_to_file(file_name)
|
126
|
+
</code>
|
127
|
+
</pre>
|
128
|
+
|
129
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/03_changed_ranges.png((03) changed ranges)!
|
130
|
+
|
131
|
+
|
132
|
+
p. Keep in mind that ranges will be changed but any point of graph can enlarge ranges that all points will be visible, unless...
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
h2. Fixed ranges
|
139
|
+
|
140
|
+
p. You can turn off automatic range enlargement algorithm by using:
|
141
|
+
|
142
|
+
<pre>
|
143
|
+
<code>
|
144
|
+
options[:xy_behaviour] = :fixed
|
145
|
+
</code>
|
146
|
+
</pre>
|
147
|
+
|
148
|
+
Example:
|
149
|
+
|
150
|
+
<pre>
|
151
|
+
<code>
|
152
|
+
@simple_data_array = [
|
153
|
+
{ :x => 0, :y => 0 },
|
154
|
+
{ :x => 1, :y => 1 },
|
155
|
+
{ :x => 2, :y => 2 },
|
156
|
+
{ :x => 3, :y => 2 },
|
157
|
+
{ :x => 4, :y => 1 },
|
158
|
+
{ :x => 5, :y => 0 },
|
159
|
+
]
|
160
|
+
|
161
|
+
@tg = TechnicalGraph.new(
|
162
|
+
{
|
163
|
+
:x_min => 1,
|
164
|
+
:x_max => 2,
|
165
|
+
:y_min => 1,
|
166
|
+
:y_max => 2,
|
167
|
+
:xy_behaviour => :fixed,
|
168
|
+
})
|
169
|
+
|
170
|
+
@tg.add_layer(@simple_data_array)
|
171
|
+
@tg.render
|
172
|
+
file_name = 'samples/readme/04_changed_ranges_fixed.png'
|
173
|
+
@tg.image_drawer.save_to_file(file_name)
|
174
|
+
</code>
|
175
|
+
</pre>
|
176
|
+
|
177
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/04_changed_ranges_fixed.png((04) changed ranges)!
|
178
|
+
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
h2. Axis interval - fixed count
|
183
|
+
|
184
|
+
p. Axis can be calculated using two algorithms:
|
185
|
+
|
186
|
+
# fixed interval - axis is every some distance,
|
187
|
+
# fixed count - there is fixed amount of axis on graph.
|
188
|
+
|
189
|
+
p. Keep in mind that where is X (parameter) and Y (value) axis. If you want to set fixed amount you should set
|
190
|
+
options[:x_axis_fixed_interval] and/or options[:y_axis_fixed_interval] to false, like in the example below.
|
191
|
+
|
192
|
+
<pre>
|
193
|
+
<code>
|
194
|
+
@simple_data_array = [
|
195
|
+
{ :x => 0, :y => 0 },
|
196
|
+
{ :x => 1, :y => 1 },
|
197
|
+
{ :x => 2, :y => 2 },
|
198
|
+
{ :x => 3, :y => 2 },
|
199
|
+
{ :x => 4, :y => 1 },
|
200
|
+
{ :x => 5, :y => 0 },
|
201
|
+
]
|
202
|
+
|
203
|
+
@tg = TechnicalGraph.new(
|
204
|
+
{
|
205
|
+
:x_axis_fixed_interval => false,
|
206
|
+
:y_axis_fixed_interval => false,
|
207
|
+
:y_axis_count => 20,
|
208
|
+
:x_axis_count => 20,
|
209
|
+
})
|
210
|
+
|
211
|
+
@tg.add_layer(@simple_data_array)
|
212
|
+
@tg.render
|
213
|
+
file_name = 'samples/readme/05_axis_fixed_amount.png'
|
214
|
+
@tg.image_drawer.save_to_file(file_name)
|
215
|
+
</code>
|
216
|
+
</pre>
|
217
|
+
|
218
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/05_axis_fixed_amount.png((05) fixed axis count)!
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
h2. Axis interval - fixed interval
|
224
|
+
|
225
|
+
p. Axis can be calculated using two algorithms:
|
226
|
+
|
227
|
+
# fixed interval - axis is every some distance,
|
228
|
+
# fixed count - there is fixed amount of axis on graph.
|
229
|
+
|
230
|
+
p. Keep in mind that where is X (parameter) and Y (value) axis. If you want to set fixed amount you should set
|
231
|
+
options[:x_axis_fixed_interval] and/or options[:y_axis_fixed_interval] to false, like in the example below.
|
232
|
+
|
233
|
+
<pre>
|
234
|
+
<code>
|
235
|
+
@simple_data_array = [
|
236
|
+
{ :x => 0, :y => 0 },
|
237
|
+
{ :x => 1, :y => 1 },
|
238
|
+
{ :x => 2, :y => 2 },
|
239
|
+
{ :x => 3, :y => 2 },
|
240
|
+
{ :x => 4, :y => 1 },
|
241
|
+
{ :x => 5, :y => 0 },
|
242
|
+
]
|
243
|
+
|
244
|
+
@tg = TechnicalGraph.new(
|
245
|
+
{
|
246
|
+
:x_axis_fixed_interval => true,
|
247
|
+
:y_axis_fixed_interval => true,
|
248
|
+
:y_axis_interval => 0.8,
|
249
|
+
:x_axis_interval => 0.6,
|
250
|
+
})
|
251
|
+
@tg.add_layer(@simple_data_array)
|
252
|
+
@tg.render
|
253
|
+
file_name = 'samples/readme/06_axis_fixed_interval.png'
|
254
|
+
@tg.image_drawer.save_to_file(file_name)
|
255
|
+
</code>
|
256
|
+
</pre>
|
257
|
+
|
258
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/06_axis_fixed_interval.png((06) fixed axis interval)!
|
259
|
+
|
260
|
+
|
261
|
+
|
262
|
+
|
263
|
+
|
264
|
+
|
265
|
+
h2. Axis labels
|
266
|
+
|
267
|
+
p. You can add label to X and Y axis. using options[:x_axis_label] and options[:y_axis_label], and you can choose font
|
268
|
+
size using options[:axis_label_font_size].
|
269
|
+
|
270
|
+
<pre>
|
271
|
+
<code>
|
272
|
+
@simple_data_array = [
|
273
|
+
{ :x => 0, :y => 0 },
|
274
|
+
{ :x => 1, :y => 1 },
|
275
|
+
{ :x => 2, :y => 2 },
|
276
|
+
{ :x => 3, :y => 2 },
|
277
|
+
{ :x => 4, :y => 1 },
|
278
|
+
{ :x => 5, :y => 0 },
|
279
|
+
]
|
280
|
+
|
281
|
+
@tg = TechnicalGraph.new(
|
282
|
+
{
|
283
|
+
:x_axis_label => 'parameter',
|
284
|
+
:y_axis_label => 'value',
|
285
|
+
:axis_label_font_size => 36
|
286
|
+
})
|
287
|
+
@@tg.add_layer(@simple_data_array)
|
288
|
+
@tg.render
|
289
|
+
file_name = 'samples/readme/07_axis_label.png'
|
290
|
+
@tg.image_drawer.save_to_file(file_name)
|
291
|
+
</code>
|
292
|
+
</pre>
|
293
|
+
|
294
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/07_axis_label.png((07) axis labels)!
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
h2. Float numbers and value labels
|
299
|
+
|
300
|
+
p. On default all float number are shown using 2 digits after dot. You can override it using options[:truncate_string]
|
301
|
+
like in example below. If you want have values near graph points you can use proper layer options.
|
302
|
+
|
303
|
+
p. Layers have also options, and it is useful for this example to turn on value labels.
|
304
|
+
|
305
|
+
layer_options[:value_labels]
|
306
|
+
|
307
|
+
<pre>
|
308
|
+
<code>
|
309
|
+
@float_data_array = [
|
310
|
+
{ :x => 0, :y => 0 },
|
311
|
+
{ :x => 0.111, :y => 0.123 },
|
312
|
+
{ :x => 0.222, :y => 1.456 },
|
313
|
+
{ :x => 0.333, :y => 2.8756 },
|
314
|
+
{ :x => 0.555, :y => 1.042 },
|
315
|
+
{ :x => 0.888, :y => 0.988 },
|
316
|
+
]
|
317
|
+
|
318
|
+
@tg = TechnicalGraph.new(
|
319
|
+
{
|
320
|
+
:truncate_string => "%.3f"
|
321
|
+
})
|
322
|
+
@layer_params = {
|
323
|
+
:value_labels => true
|
324
|
+
}
|
325
|
+
@tg.add_layer(@float_data_array, @layer_params)
|
326
|
+
@tg.render
|
327
|
+
file_name = 'samples/readme/08a_truncate_string.png'
|
328
|
+
@tg.image_drawer.save_to_file(file_name)
|
329
|
+
</code>
|
330
|
+
</pre>
|
331
|
+
|
332
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/08a_truncate_string.png((08a) displaying float numbers)!
|
333
|
+
|
334
|
+
<pre>
|
335
|
+
<code>
|
336
|
+
@float_data_array = [
|
337
|
+
{ :x => 0, :y => 0 },
|
338
|
+
{ :x => 0.111, :y => 0.123 },
|
339
|
+
{ :x => 0.222, :y => 1.456 },
|
340
|
+
{ :x => 0.333, :y => 2.8756 },
|
341
|
+
{ :x => 0.555, :y => 1.042 },
|
342
|
+
{ :x => 0.888, :y => 0.988 },
|
343
|
+
]
|
344
|
+
|
345
|
+
@tg = TechnicalGraph.new(
|
346
|
+
{
|
347
|
+
:truncate_string => "%.1f"
|
348
|
+
})
|
349
|
+
@layer_params = {
|
350
|
+
:value_labels => true
|
351
|
+
}
|
352
|
+
@tg.add_layer(@float_data_array, @layer_params)
|
353
|
+
@tg.render
|
354
|
+
file_name = 'samples/readme/08b_truncate_string.png'
|
355
|
+
@tg.image_drawer.save_to_file(file_name)
|
356
|
+
</code>
|
357
|
+
</pre>
|
358
|
+
|
359
|
+
!https://github.com/akwiatkowski/technical_graph/raw/master/samples/readme/08b_truncate_string.png((08b) displaying float numbers)!
|
360
|
+
|
361
|
+
|
362
|
+
h2. TODO
|
363
|
+
|
364
|
+
# Graph image size
|
365
|
+
# Graph colors: background, hatch (option to turn it off?), axis
|
366
|
+
# Anti-aliasing: image size comparison, layer antialiases
|
367
|
+
# Font sizes
|
368
|
+
# Axis density checking algorithm: sample when it us useful
|
369
|
+
# Layer labels: used in legend
|
370
|
+
# Layer colors, random colors
|
371
|
+
# Legend with set position
|
372
|
+
# Legend with auto position
|
373
|
+
# Smoother:
|
374
|
+
# Noise removal
|
data/README.md
CHANGED
@@ -1,11 +1,38 @@
|
|
1
|
-
|
1
|
+
technical_graph
|
2
2
|
===============
|
3
3
|
|
4
|
-
|
4
|
+
Purpose of this gem is to create neat, meaningful, linear graphs for large amount of data.
|
5
5
|
|
6
|
+
If you want to:
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
* create big graphs using large amount of data,
|
9
|
+
* do it offline,
|
10
|
+
* minimize needed code,
|
11
|
+
* use only linear graph,
|
12
|
+
* speed is not essential,
|
13
|
+
* RMagick / ImageMagick is ok for you,
|
14
|
+
* tired of forgotten gems/libraries...
|
15
|
+
|
16
|
+
then you should try this gem.
|
17
|
+
|
18
|
+
I created it because there were not available and maintained gems for that I needed. Now I use it to create hourly
|
19
|
+
temperature and wind graphs for vast period of time (months, years), visualize measurements for [HomeIO](https://github.com/akwiatkowski/HomeIO).
|
20
|
+
|
21
|
+
If you want to create candy, ultra fast, web graphs it maybe not the best tool. If you want other graph types than linear it
|
22
|
+
is definitely not the right tool for you. It is also not SVG ready yet, but it should be within a few months.
|
23
|
+
You can find my competitors [here](https://www.ruby-toolbox.com/categories/graphing).
|
24
|
+
|
25
|
+
|
26
|
+
Future
|
27
|
+
------
|
28
|
+
|
29
|
+
1. Finish data processors: smoothing (nearly done), noise removal (50%), interpolation or curved graphs (planned).
|
30
|
+
2. Fix export to SVG.
|
31
|
+
3. Optimization, and if needed find or write something faster for creating SVGs.
|
32
|
+
|
33
|
+
|
34
|
+
Quick start
|
35
|
+
-----------
|
9
36
|
|
10
37
|
Check currents test when documentation is not enough :)
|
11
38
|
|
@@ -32,7 +59,7 @@ or
|
|
32
59
|
where:
|
33
60
|
|
34
61
|
* layer_data - Array of Hashes, like [{:x => 0, :y => 0}, {:x => 1, :y => 1}, ...]
|
35
|
-
* layer_params - Hash of other parameters, all parameters
|
62
|
+
* layer_params - Hash of other parameters, all parameters are described later.
|
36
63
|
|
37
64
|
3. Render graph
|
38
65
|
|
@@ -46,101 +73,13 @@ or get image binary content.
|
|
46
73
|
|
47
74
|
> tg.image_drawer.to_format(format)
|
48
75
|
|
49
|
-
where format is image format, ex. 'png', 'jpeg', ...
|
76
|
+
where format is image format, ex. 'png', 'jpeg', ... Of course I prefer 'png'.
|
50
77
|
|
51
78
|
|
52
|
-
|
79
|
+
Documentation
|
53
80
|
-------------
|
54
81
|
|
55
|
-
|
56
|
-
|
57
|
-
* options[:x_min]
|
58
|
-
* options[:x_max]
|
59
|
-
* options[:y_min]
|
60
|
-
* options[:y_max]
|
61
|
-
|
62
|
-
Ranges calculation mode:
|
63
|
-
|
64
|
-
* options[:xy_behaviour] = :default - ranges can be enlarged
|
65
|
-
* options[:xy_behaviour] = :fixed - fixed ranges
|
66
|
-
|
67
|
-
Axis can be calculated using fixed interval or fixed count per graph.
|
68
|
-
|
69
|
-
* options[:x_axis_fixed_interval] = true
|
70
|
-
* options[:y_axis_fixed_interval] = true
|
71
|
-
|
72
|
-
If fixed interval is set you should specify interval:
|
73
|
-
|
74
|
-
* options[:y_axis_interval] = 1.0
|
75
|
-
* options[:x_axis_interval] = 1.0
|
76
|
-
|
77
|
-
...else, count of axis:
|
78
|
-
|
79
|
-
* options[:y_axis_count] = 10
|
80
|
-
* options[:x_axis_count] = 10
|
81
|
-
|
82
|
-
Axis labels:
|
83
|
-
|
84
|
-
* options[:x_axis_label] = 'x'
|
85
|
-
* options[:y_axis_label] = 'y'
|
86
|
-
|
87
|
-
|
88
|
-
Labels has truncate string to define precision. Default it is "%.2f".
|
89
|
-
|
90
|
-
* options[:truncate_string] = "%.2f"
|
91
|
-
|
92
|
-
Graph image size:
|
93
|
-
|
94
|
-
* options[:width]
|
95
|
-
* options[:height]
|
96
|
-
|
97
|
-
Colors:
|
98
|
-
|
99
|
-
Possible #RRGGBB or color names (ex. 'white').
|
100
|
-
|
101
|
-
* options[:background_color] - background color of image
|
102
|
-
* options[:background_hatch_color] - background hatch color
|
103
|
-
* options[:axis_color] - color of axis
|
104
|
-
|
105
|
-
Anti-aliasing:
|
106
|
-
|
107
|
-
* options[:axis_antialias] - use anti-aliasing for axis, default false
|
108
|
-
* options[:layers_antialias] - use anti-aliasing for data layers, default false, can be override using layer option
|
109
|
-
* options[:font_antialias] - use anti-aliasing for all fonts, default false
|
110
|
-
|
111
|
-
Font size:
|
112
|
-
|
113
|
-
* options[:layers_font_size] - size of font used for values in graph
|
114
|
-
* options[:axis_font_size] - size of font used in axis
|
115
|
-
* options[:axis_label_font_size] - size of font used in options[:x_axis_label] and options[:y_axis_label]
|
116
|
-
|
117
|
-
Sometime because of axis options and large amount of data, axis can be put densely on graph. Turning this option graph
|
118
|
-
size will be enlarged to maintain set distanced between axis.
|
119
|
-
|
120
|
-
* options[:axis_density_enlarge_image] - turn this options on
|
121
|
-
* options[:x_axis_min_distance] - minimum distance between X axis, default 30 pixels
|
122
|
-
* options[:y_axis_min_distance] - minimum distance between X axis, default 50 pixels
|
123
|
-
|
124
|
-
Legend options:
|
125
|
-
|
126
|
-
* options[:legend] - do you want to draw legend?, default false
|
127
|
-
* options[:legend_auto] - let legend position to be chosen by algorithm, default true
|
128
|
-
* options[:legend_width] - width used for setting proper distance while drawing on right, default 100, legend height is calculated
|
129
|
-
* options[:legend_margin] - graph margin used not to draw legend on border, default 50
|
130
|
-
* options[:legend_x] - legend X position, used when options[:legend_auto] is false, default 50
|
131
|
-
* options[:legend_y] - legend Y position, used when options[:legend_auto] is false, default 50
|
132
|
-
|
133
|
-
|
134
|
-
Layer options Hash
|
135
|
-
------------------
|
136
|
-
|
137
|
-
* layer_options[:label] - label used in legend
|
138
|
-
* layer_options[:color] - color of graph layer, ex.: 'red', 'green', '#FFFF00'
|
139
|
-
* layer_options[:antialias] - use anti-aliasing for this, default false, override options[:layers_antialias]
|
140
|
-
* layer_options[:value_labels] - write values near 'dots', default true
|
141
|
-
* layer_options[:simple_smoother] - 'smooth' data, default false
|
142
|
-
* layer_options[:simple_smoother_level] - strength of smoothing, this is level of window used for processing, default 3
|
143
|
-
* layer_options[:simple_smoother_strategy] - strategy used for smoothing data, you can choose between :rectangular or :gauss, default :rectangular
|
82
|
+
Documentation is moved [here](https://github.com/akwiatkowski/technical_graph/blob/master/DOCUMENTATION.textile)
|
144
83
|
|
145
84
|
|
146
85
|
Contributing to technical-graph
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
@@ -1,5 +1,6 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
|
3
|
+
require 'technical_graph/data_point'
|
3
4
|
require 'technical_graph/graph_color_library'
|
4
5
|
require 'technical_graph/data_layer_processor'
|
5
6
|
|
@@ -20,8 +21,9 @@ class DataLayer
|
|
20
21
|
# smoothing parameters
|
21
22
|
# by default it is false
|
22
23
|
@data_params[:simple_smoother] = true if options[:simple_smoother] == true
|
24
|
+
@data_params[:simple_smoother_x] = true if options[:simple_smoother_x] == true
|
23
25
|
@data_params[:simple_smoother_level] ||= 3
|
24
|
-
@data_params[:simple_smoother_strategy] ||= DataLayerProcessor::
|
26
|
+
@data_params[:simple_smoother_strategy] ||= DataLayerProcessor::DEFAULT_SIMPLE_SMOOTHER_STRATEGY
|
25
27
|
# was already done
|
26
28
|
@data_params[:processor_finished] = false
|
27
29
|
|
@@ -36,29 +38,42 @@ class DataLayer
|
|
36
38
|
attr_reader :processor
|
37
39
|
|
38
40
|
# Accessor for setting chart data for layer to draw
|
39
|
-
def append_data(
|
40
|
-
if
|
41
|
-
|
41
|
+
def append_data(data_array)
|
42
|
+
if data_array.kind_of? Array
|
43
|
+
# append as DataPoint
|
44
|
+
# convert to DataPoints, which has more specialized methods
|
45
|
+
data_array.each do |d|
|
46
|
+
@data << DataPoint.new(d)
|
47
|
+
end
|
48
|
+
|
42
49
|
# sort, clean bad records
|
43
|
-
|
50
|
+
process_data_internal
|
51
|
+
|
52
|
+
# @raw_data is dirty, deleting @processed_data
|
53
|
+
@processed_data = nil
|
44
54
|
else
|
45
55
|
raise 'Data not an Array'
|
46
56
|
end
|
47
57
|
end
|
48
58
|
|
49
|
-
# Array of
|
50
|
-
|
59
|
+
# Array of DataPoints, not processed
|
60
|
+
def raw_data
|
61
|
+
@data
|
62
|
+
end
|
51
63
|
|
52
|
-
#
|
53
|
-
def
|
54
|
-
if
|
55
|
-
|
56
|
-
@processor.level = simple_smoother_level
|
57
|
-
@processor.generate_vector
|
58
|
-
@data = @processor.process
|
59
|
-
|
60
|
-
processor_finished!
|
64
|
+
# Array of DataPoints, after external processing
|
65
|
+
def processed_data
|
66
|
+
if @processed_data.nil?
|
67
|
+
process!
|
61
68
|
end
|
69
|
+
|
70
|
+
@processed_data
|
71
|
+
end
|
72
|
+
|
73
|
+
# Run external processor (smoothing, ...)
|
74
|
+
def process!
|
75
|
+
@processed_data = @data.clone
|
76
|
+
@processed_data = @processor.process
|
62
77
|
end
|
63
78
|
|
64
79
|
# Additional parameters
|
@@ -97,14 +112,8 @@ class DataLayer
|
|
97
112
|
return @data_params[:simple_smoother_strategy]
|
98
113
|
end
|
99
114
|
|
100
|
-
|
101
|
-
|
102
|
-
@data_params[:processor_finished]
|
103
|
-
end
|
104
|
-
|
105
|
-
# Mark as processed
|
106
|
-
def processor_finished!
|
107
|
-
@data_params[:processor_finished] = true
|
115
|
+
def simple_smoother_x
|
116
|
+
return @data_params[:simple_smoother_x]
|
108
117
|
end
|
109
118
|
|
110
119
|
# Clear data
|
@@ -113,24 +122,23 @@ class DataLayer
|
|
113
122
|
end
|
114
123
|
|
115
124
|
# Clean and process data used for drawing current data layer
|
116
|
-
def
|
125
|
+
def process_data_internal
|
117
126
|
# delete duplicates
|
118
|
-
@data = @data.inject([]) { |result, d| result << d unless result.select { |r| r
|
127
|
+
@data = @data.inject([]) { |result, d| result << d unless result.select { |r| r.x == d.x }.size > 0; result }
|
119
128
|
|
120
|
-
@data.delete_if { |d| d
|
121
|
-
@data.sort! { |d, e| d
|
129
|
+
@data.delete_if { |d| d.x.nil? or d.y.nil? }
|
130
|
+
@data.sort! { |d, e| d.x <=> e.x }
|
122
131
|
|
123
132
|
# default X values, if data is not empty
|
124
133
|
if @data.size > 0
|
125
|
-
@data_params[:x_min] = @data.first
|
126
|
-
@data_params[:x_max] = @data.last
|
134
|
+
@data_params[:x_min] = @data.first.x || @options[:default_x_min]
|
135
|
+
@data_params[:x_max] = @data.last.x || @options[:default_x_max]
|
127
136
|
|
128
137
|
# default Y values
|
129
|
-
y_sort = @data.sort { |a, b| a
|
130
|
-
@data_params[:y_min] = y_sort.first
|
131
|
-
@data_params[:y_max] = y_sort.last
|
138
|
+
y_sort = @data.sort { |a, b| a.y <=> b.y }
|
139
|
+
@data_params[:y_min] = y_sort.first.y || @options[:default_y_min]
|
140
|
+
@data_params[:y_max] = y_sort.last.y || @options[:@default_y_max]
|
132
141
|
end
|
133
|
-
|
134
142
|
end
|
135
143
|
|
136
144
|
def x_min
|