technical_graph 0.5.1 → 0.6.0
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 +244 -171
- data/Gemfile +26 -5
- data/Gemfile.lock +30 -14
- data/README.md +68 -39
- data/Rakefile +16 -14
- data/VERSION +1 -1
- data/lib/technical_graph.rb +45 -0
- data/lib/technical_graph/data_layer_processor_simple_smoother.rb +1 -1
- data/lib/technical_graph/gem.rb +12 -0
- data/lib/technical_graph/graph_axis.rb +14 -7
- data/lib/technical_graph/graph_color_library.rb +5 -5
- data/lib/technical_graph/graph_data_processor.rb +3 -1
- data/lib/technical_graph/graph_image_drawer.rb +35 -12
- data/lib/technical_graph/graph_image_drawer_chunky.rb +161 -0
- data/lib/technical_graph/graph_image_drawer_rmagick.rb +6 -2
- metadata +119 -135
- data/test/helper.rb +0 -23
- data/test/test_technical_autocolor.rb +0 -92
- data/test/test_technical_axis_enlarge.rb +0 -68
- data/test/test_technical_fix1.rb +0 -64
- data/test/test_technical_graph.rb +0 -115
- data/test/test_technical_graph_axis.rb +0 -314
- data/test/test_technical_multilayer.rb +0 -96
- data/test/test_technical_noise_removal.rb +0 -36
- data/test/test_technical_rasem.rb +0 -22
- data/test/test_technical_readme.rb +0 -525
- data/test/test_technical_simple_graph.rb +0 -64
- data/test/test_technical_smoother.rb +0 -214
- data/test/test_technical_smoother_adv.rb +0 -125
data/Gemfile
CHANGED
@@ -1,11 +1,32 @@
|
|
1
|
+
# hack for loading gems if they were are available to add
|
2
|
+
# some optional features
|
3
|
+
def gem_available?(name)
|
4
|
+
Gem::Specification.find_by_name(name)
|
5
|
+
rescue Gem::LoadError
|
6
|
+
false
|
7
|
+
rescue
|
8
|
+
Gem.available?(name)
|
9
|
+
end
|
10
|
+
|
11
|
+
|
1
12
|
source "http://rubygems.org"
|
2
13
|
|
14
|
+
# SVG
|
3
15
|
gem 'rasem'
|
4
16
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
|
17
|
+
# PNG
|
18
|
+
gem 'chunky_png'
|
19
|
+
gem 'rmagick' if gem_available? 'rmagick'
|
20
|
+
gem 'oily_png' if gem_available? 'oily_png'
|
21
|
+
|
22
|
+
# optional gem - creating graphs using ImageMagic
|
23
|
+
#if Gem.source_index.find_name('rmagick').size > 0
|
24
|
+
# gem 'rmagick'
|
25
|
+
#end
|
26
|
+
# optional gem - chunky_png C addon
|
27
|
+
#if Gem.source_index.find_name('oily_png').size > 0
|
28
|
+
# gem 'oily_png'
|
29
|
+
#end
|
9
30
|
|
10
31
|
# Add dependencies to develop your gem here.
|
11
32
|
# Include everything needed to run rake, tests, features, etc.
|
@@ -15,5 +36,5 @@ group :development do
|
|
15
36
|
gem "bundler", "~> 1.0.0"
|
16
37
|
gem "rspec"
|
17
38
|
gem "jeweler" #, "~> 1.6.4"
|
18
|
-
gem "
|
39
|
+
gem "simplecov", ">= 0"
|
19
40
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,36 +1,52 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
chunky_png (1.2.5)
|
4
5
|
diff-lcs (1.1.3)
|
5
6
|
git (1.2.5)
|
6
|
-
jeweler (1.
|
7
|
+
jeweler (1.8.3)
|
7
8
|
bundler (~> 1.0)
|
8
9
|
git (>= 1.2.5)
|
9
10
|
rake
|
10
|
-
|
11
|
+
rdoc
|
12
|
+
json (1.7.3)
|
13
|
+
multi_json (1.3.5)
|
14
|
+
oily_png (1.0.2)
|
15
|
+
chunky_png (~> 1.2.1)
|
11
16
|
rake (0.9.2.2)
|
12
17
|
rasem (0.6.1)
|
13
|
-
|
14
|
-
rdoc (3.11)
|
18
|
+
rdoc (3.12)
|
15
19
|
json (~> 1.4)
|
16
|
-
|
17
|
-
|
18
|
-
rspec-
|
19
|
-
rspec-
|
20
|
-
|
21
|
-
rspec-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
rmagick (2.13.1)
|
21
|
+
rspec (2.10.0)
|
22
|
+
rspec-core (~> 2.10.0)
|
23
|
+
rspec-expectations (~> 2.10.0)
|
24
|
+
rspec-mocks (~> 2.10.0)
|
25
|
+
rspec-core (2.10.1)
|
26
|
+
rspec-expectations (2.10.0)
|
27
|
+
diff-lcs (~> 1.1.3)
|
28
|
+
rspec-mocks (2.10.1)
|
29
|
+
shoulda (3.0.1)
|
30
|
+
shoulda-context (~> 1.0.0)
|
31
|
+
shoulda-matchers (~> 1.0.0)
|
32
|
+
shoulda-context (1.0.0)
|
33
|
+
shoulda-matchers (1.0.0)
|
34
|
+
simplecov (0.6.4)
|
35
|
+
multi_json (~> 1.0)
|
36
|
+
simplecov-html (~> 0.5.3)
|
37
|
+
simplecov-html (0.5.3)
|
25
38
|
|
26
39
|
PLATFORMS
|
27
40
|
ruby
|
28
41
|
|
29
42
|
DEPENDENCIES
|
30
43
|
bundler (~> 1.0.0)
|
44
|
+
chunky_png
|
31
45
|
jeweler
|
46
|
+
oily_png
|
32
47
|
rasem
|
33
|
-
rcov
|
34
48
|
rdoc
|
49
|
+
rmagick
|
35
50
|
rspec
|
36
51
|
shoulda
|
52
|
+
simplecov
|
data/README.md
CHANGED
@@ -3,83 +3,113 @@ technical_graph
|
|
3
3
|
|
4
4
|
Purpose of this gem is to create neat, meaningful, linear graphs for large amount of data.
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
*
|
9
|
-
* do it offline,
|
6
|
+
When you want to:
|
7
|
+
* create big graph using large amount of data,
|
8
|
+
* do it offline and speed is not the most important factor,
|
10
9
|
* minimize needed code,
|
11
10
|
* use only linear graph,
|
12
|
-
* speed is not essential,
|
13
11
|
* RMagick / ImageMagick is ok for you,
|
14
12
|
* tired of forgotten gems/libraries...
|
15
13
|
|
16
|
-
|
14
|
+
Then you should try this gem.
|
17
15
|
|
18
16
|
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).
|
17
|
+
temperature and wind speed graphs for vast period of time (months, years), visualize measurements for [HomeIO](https://github.com/akwiatkowski/HomeIO).
|
24
18
|
|
19
|
+
If you want to create candy, ultra fast, web graphs it is maybe not the best tool. If you want other graph types than linear it
|
20
|
+
is definitely not the right tool for you. You can find my competitors [here](https://www.ruby-toolbox.com/categories/graphing).
|
25
21
|
|
26
22
|
Future
|
27
23
|
------
|
28
24
|
|
29
|
-
1.
|
30
|
-
2.
|
31
|
-
3. Optimization, and if needed find or write something faster for creating SVGs.
|
32
|
-
|
25
|
+
1. Curved graphs.
|
26
|
+
2. Bug fixes, cleaning.
|
33
27
|
|
34
28
|
Quick start
|
35
29
|
-----------
|
36
30
|
|
37
|
-
Check currents test
|
31
|
+
Check currents test if documentation is not enough :)
|
32
|
+
|
33
|
+
* Create 'the instance'
|
34
|
+
|
35
|
+
> tg = TechnicalGraph.new
|
36
|
+
|
37
|
+
or
|
38
|
+
|
39
|
+
> tg = TechnicalGraph.new( options )
|
40
|
+
|
41
|
+
where:
|
42
|
+
|
43
|
+
+ options - Hash of parameters, all parameters are described [here](https://github.com/akwiatkowski/technical_graph/blob/master/DOCUMENTATION.textile).
|
44
|
+
|
45
|
+
* Add layer
|
46
|
+
|
47
|
+
> tg.add_layer(layer_data)
|
38
48
|
|
39
|
-
|
49
|
+
or
|
40
50
|
|
41
|
-
> tg
|
51
|
+
> tg.add_layer(layer_data, layer_params)
|
42
52
|
|
43
|
-
|
53
|
+
where:
|
44
54
|
|
45
|
-
|
55
|
+
+ layer_data - Array of Hashes, like [{:x => 0, :y => 0}, {:x => 1, :y => 1}, ...]
|
56
|
+
+ layer_params - Hash of other parameters, all parameters are described [here](https://github.com/akwiatkowski/technical_graph/blob/master/DOCUMENTATION.textile).
|
46
57
|
|
47
|
-
|
58
|
+
* Save to file
|
48
59
|
|
49
|
-
|
60
|
+
> tg.save_to_file('image.svg')
|
50
61
|
|
51
|
-
|
62
|
+
or
|
52
63
|
|
53
|
-
> tg.
|
64
|
+
> tg.save_to_file('image.svgz')
|
54
65
|
|
55
|
-
or
|
66
|
+
or
|
56
67
|
|
57
|
-
> tg.
|
68
|
+
> tg.save_to_file('image.png')
|
69
|
+
|
70
|
+
|
71
|
+
or get binary version of output using
|
72
|
+
|
73
|
+
> tg.to_format(format) # where format is 'svg', 'svgz', 'png', ...
|
74
|
+
|
75
|
+
|
76
|
+
This is the new, easiest, better and nicer approach because technical_graph render graph
|
77
|
+
using appropriate drawer to file extension.
|
78
|
+
|
79
|
+
|
80
|
+
Some notes about formats and dependencies
|
81
|
+
-----------------------------------------
|
82
|
+
|
83
|
+
technical_graph uses [rasem](https://github.com/aseldawy/rasem) for SVG and it works wery well.
|
84
|
+
For PNG it uses [chunky_png](https://github.com/wvanbergen/chunky_png) with [oily_png](https://github.com/wvanbergen/oily_png)
|
85
|
+
if possible, but there is a lot of missing features. If you need PNG I recommend to install
|
86
|
+
good, old [rmagick](https://github.com/rmagick/rmagick).
|
87
|
+
|
88
|
+
|
89
|
+
An old way
|
90
|
+
-------------
|
58
91
|
|
59
|
-
|
92
|
+
Up to version 0.5.1 you had to render image before you could save it to file. It should work in current version too.
|
60
93
|
|
61
|
-
*
|
62
|
-
* layer_params - Hash of other parameters, all parameters are described later.
|
94
|
+
* Render graph
|
63
95
|
|
64
|
-
|
96
|
+
> tg.render
|
65
97
|
|
66
|
-
|
98
|
+
* Save to file
|
67
99
|
|
68
|
-
|
100
|
+
> tg.image_drawer.save_to_file('image.png')
|
69
101
|
|
70
|
-
|
102
|
+
or get image binary content.
|
71
103
|
|
72
|
-
|
104
|
+
> tg.image_drawer.to_format(format)
|
73
105
|
|
74
|
-
> tg.image_drawer.to_format(format)
|
75
106
|
|
76
|
-
where format is image format, ex. 'png', 'jpeg', ... Of course I prefer 'png'.
|
77
107
|
|
78
108
|
|
79
109
|
Documentation
|
80
110
|
-------------
|
81
111
|
|
82
|
-
Documentation
|
112
|
+
Documentation was moved [here](https://github.com/akwiatkowski/technical_graph/blob/master/DOCUMENTATION.textile)
|
83
113
|
|
84
114
|
|
85
115
|
Contributing to technical-graph
|
@@ -99,6 +129,5 @@ Contributing to technical-graph
|
|
99
129
|
Copyright
|
100
130
|
---------
|
101
131
|
|
102
|
-
Copyright (c) 2011 Aleksander Kwiatkowski. See LICENSE.txt for
|
103
|
-
further details.
|
132
|
+
Copyright (c) 2011-2012 Aleksander Kwiatkowski. See LICENSE.txt for further details.
|
104
133
|
|
data/Rakefile
CHANGED
@@ -41,29 +41,31 @@ desc "Clean and release"
|
|
41
41
|
task :clean_and_release => [:clean, :release] do
|
42
42
|
end
|
43
43
|
|
44
|
-
require '
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
test.verbose = true
|
44
|
+
require 'rspec/core'
|
45
|
+
require 'rspec/core/rake_task'
|
46
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
47
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
49
48
|
end
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
test.pattern = 'test/**/test_*.rb'
|
55
|
-
test.verbose = true
|
56
|
-
test.rcov_opts << '--exclude "gems/*"'
|
50
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
51
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
52
|
+
spec.rcov = true
|
57
53
|
end
|
58
54
|
|
59
|
-
task :default => :
|
55
|
+
task :default => :spec
|
60
56
|
|
61
|
-
require '
|
57
|
+
require 'rake/rdoctask'
|
62
58
|
Rake::RDocTask.new do |rdoc|
|
63
59
|
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
64
60
|
|
65
61
|
rdoc.rdoc_dir = 'rdoc'
|
66
|
-
rdoc.title = "
|
62
|
+
rdoc.title = "gpx2exif #{version}"
|
67
63
|
rdoc.rdoc_files.include('README*')
|
68
64
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
69
65
|
end
|
66
|
+
|
67
|
+
desc "Run RSpec with code coverage"
|
68
|
+
task :coverage do
|
69
|
+
`rake spec COVERAGE=true`
|
70
|
+
#`open coverage/index.html`
|
71
|
+
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/technical_graph.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'logger'
|
5
|
+
require 'technical_graph/gem'
|
5
6
|
require 'technical_graph/data_layer'
|
6
7
|
require 'technical_graph/graph_data_processor'
|
7
8
|
require 'technical_graph/graph_image_drawer'
|
@@ -71,4 +72,48 @@ class TechnicalGraph
|
|
71
72
|
# draw legend
|
72
73
|
@image_drawer.render_data_legend
|
73
74
|
end
|
75
|
+
|
76
|
+
# Render and save graph to a file
|
77
|
+
def save_to_file(filename)
|
78
|
+
ext = File.extname(filename).gsub(/^\./, '')
|
79
|
+
pre_render(ext)
|
80
|
+
@image_drawer.save_to_file(filename)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Render and return graph string
|
84
|
+
def to_format(ext)
|
85
|
+
pre_render(ext)
|
86
|
+
@image_drawer.to_format(ext)
|
87
|
+
end
|
88
|
+
|
89
|
+
# You don't have to run this
|
90
|
+
def pre_render(ext)
|
91
|
+
case ext
|
92
|
+
when 'svg', 'svgz' then
|
93
|
+
@options[:drawer_class] = :rasem
|
94
|
+
render
|
95
|
+
|
96
|
+
when 'png' then
|
97
|
+
if gem_available?('rmagick')
|
98
|
+
# rmagick is at the moment the best solution
|
99
|
+
@options[:drawer_class] = :rmagick
|
100
|
+
else
|
101
|
+
@options[:drawer_class] = :chunky_png
|
102
|
+
end
|
103
|
+
render
|
104
|
+
|
105
|
+
when 'jpeg', 'jpg', 'bmp', 'gif' then
|
106
|
+
if rmagick_installed?
|
107
|
+
@options[:drawer_class] = :rmagick
|
108
|
+
render
|
109
|
+
else
|
110
|
+
raise Gem::LoadError
|
111
|
+
end
|
112
|
+
|
113
|
+
else
|
114
|
+
raise ArgumentError
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
74
119
|
end
|
@@ -6,7 +6,7 @@ module DataLayerProcessorSimpleSmoother
|
|
6
6
|
:rectangular => 'generate_vector_rectangular',
|
7
7
|
:gauss => 'generate_vector_gauss'
|
8
8
|
}
|
9
|
-
DEFAULT_SIMPLE_SMOOTHER_STRATEGY = :
|
9
|
+
DEFAULT_SIMPLE_SMOOTHER_STRATEGY = :gauss
|
10
10
|
|
11
11
|
MIN_SIMPLE_SMOOTHER_LEVEL = 1
|
12
12
|
MAX_SIMPLE_SMOOTHER_LEVEL = 200
|
@@ -6,6 +6,9 @@ class GraphAxis
|
|
6
6
|
|
7
7
|
attr_reader :technical_graph
|
8
8
|
|
9
|
+
# some issues with float precision and rounding
|
10
|
+
SAFE_ENL_COEFF = 1.1
|
11
|
+
|
9
12
|
# Accessor for options Hash
|
10
13
|
def options
|
11
14
|
@technical_graph.options
|
@@ -125,10 +128,10 @@ class GraphAxis
|
|
125
128
|
|
126
129
|
# Enlarge image to maintain proper axis density
|
127
130
|
def axis_distance_image_enlarge
|
128
|
-
if options[:axis_density_enlarge_image]
|
131
|
+
if options[:axis_density_enlarge_image] or options[:x_axis_density_enlarge_image] or options[:y_axis_density_enlarge_image]
|
129
132
|
t = Time.now
|
130
|
-
x_axis_distance_image_enlarge
|
131
|
-
y_axis_distance_image_enlarge
|
133
|
+
x_axis_distance_image_enlarge if options[:axis_density_enlarge_image] or options[:x_axis_density_enlarge_image]
|
134
|
+
y_axis_distance_image_enlarge if options[:axis_density_enlarge_image] or options[:y_axis_density_enlarge_image]
|
132
135
|
|
133
136
|
logger.debug "axis enlarged"
|
134
137
|
logger.debug " TIME COST #{Time.now - t}"
|
@@ -143,9 +146,9 @@ class GraphAxis
|
|
143
146
|
return if a.size < 2
|
144
147
|
|
145
148
|
ax = a[0]
|
146
|
-
ax = image.
|
149
|
+
ax = image.calc_bitmap_x(ax).round
|
147
150
|
bx = a[1]
|
148
|
-
bx = image.
|
151
|
+
bx = image.calc_bitmap_x(bx).round
|
149
152
|
|
150
153
|
axis_distance = (bx - ax).abs
|
151
154
|
|
@@ -153,7 +156,9 @@ class GraphAxis
|
|
153
156
|
if axis_distance < options[:x_axis_min_distance]
|
154
157
|
# enlarging image
|
155
158
|
options[:old_width] = options[:width]
|
156
|
-
options[:width]
|
159
|
+
options[:width] = options[:width].to_f * (options[:x_axis_min_distance].to_f / axis_distance.to_f)
|
160
|
+
options[:width] *= SAFE_ENL_COEFF
|
161
|
+
options[:width] = options[:width].ceil
|
157
162
|
logger.debug "axis enlarged - width modified to #{options[:width]}"
|
158
163
|
end
|
159
164
|
end
|
@@ -176,7 +181,9 @@ class GraphAxis
|
|
176
181
|
if axis_distance < options[:y_axis_min_distance]
|
177
182
|
# enlarging image
|
178
183
|
options[:old_height] = options[:height]
|
179
|
-
options[:height]
|
184
|
+
options[:height] = options[:height].to_f * (options[:y_axis_min_distance].to_f / axis_distance.to_f)
|
185
|
+
options[:height] *= SAFE_ENL_COEFF
|
186
|
+
options[:height] = options[:height].ceil
|
180
187
|
logger.debug "axis enlarged - height modified from #{options[:old_height]} to #{options[:height]}"
|
181
188
|
end
|
182
189
|
end
|