heatmap 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/.travis.yml +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +40 -0
- data/LICENSE.txt +20 -0
- data/README.md +76 -0
- data/Rakefile +45 -0
- data/examples/README.md +46 -0
- data/examples/large-data +50 -0
- data/examples/large.png +0 -0
- data/examples/large.rb +12 -0
- data/examples/simple.png +0 -0
- data/examples/simple.rb +11 -0
- data/heatmap.gemspec +78 -0
- data/lib/assets/gradient.png +0 -0
- data/lib/assets/point.png +0 -0
- data/lib/heatmap/area.rb +16 -0
- data/lib/heatmap/geometry.rb +25 -0
- data/lib/heatmap/image.rb +32 -0
- data/lib/heatmap/map.rb +20 -0
- data/lib/heatmap/version.rb +3 -0
- data/lib/heatmap.rb +13 -0
- data/test/helper.rb +27 -0
- data/test/test_area.rb +29 -0
- data/test/test_geometry.rb +33 -0
- data/test/test_heatmap.rb +11 -0
- data/test/test_image.rb +17 -0
- data/test/test_map.rb +23 -0
- metadata +149 -0
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
coverage.data
|
4
|
+
|
5
|
+
# rdoc generated
|
6
|
+
rdoc
|
7
|
+
|
8
|
+
# yard generated
|
9
|
+
doc
|
10
|
+
.yardoc
|
11
|
+
|
12
|
+
# bundler
|
13
|
+
.bundle
|
14
|
+
|
15
|
+
# jeweler generated
|
16
|
+
pkg
|
17
|
+
|
18
|
+
# For MacOS:
|
19
|
+
.DS_Store
|
20
|
+
|
21
|
+
# For TextMate
|
22
|
+
*.tmproj
|
23
|
+
tmtags
|
24
|
+
|
25
|
+
test/example.png
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activesupport (3.2.11)
|
5
|
+
i18n (~> 0.6)
|
6
|
+
multi_json (~> 1.0)
|
7
|
+
bourne (1.1.2)
|
8
|
+
mocha (= 0.10.5)
|
9
|
+
git (1.2.5)
|
10
|
+
i18n (0.6.1)
|
11
|
+
jeweler (1.8.4)
|
12
|
+
bundler (~> 1.0)
|
13
|
+
git (>= 1.2.5)
|
14
|
+
rake
|
15
|
+
rdoc
|
16
|
+
json (1.7.6)
|
17
|
+
metaclass (0.0.1)
|
18
|
+
mocha (0.10.5)
|
19
|
+
metaclass (~> 0.0.1)
|
20
|
+
multi_json (1.5.0)
|
21
|
+
rake (10.0.3)
|
22
|
+
rdoc (3.12)
|
23
|
+
json (~> 1.4)
|
24
|
+
shoulda (3.3.2)
|
25
|
+
shoulda-context (~> 1.0.1)
|
26
|
+
shoulda-matchers (~> 1.4.1)
|
27
|
+
shoulda-context (1.0.2)
|
28
|
+
shoulda-matchers (1.4.2)
|
29
|
+
activesupport (>= 3.0.0)
|
30
|
+
bourne (~> 1.1.2)
|
31
|
+
yard (0.8.3)
|
32
|
+
|
33
|
+
PLATFORMS
|
34
|
+
ruby
|
35
|
+
|
36
|
+
DEPENDENCIES
|
37
|
+
bundler
|
38
|
+
jeweler (~> 1.8.4)
|
39
|
+
shoulda
|
40
|
+
yard (~> 0.7)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Thiago Jackiw
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# heatmap [![Build Status](https://secure.travis-ci.org/tjackiw/heatmap.png)](https://travis-ci.org/tjackiw/heatmap)
|
2
|
+
|
3
|
+
Simple Heatmap generator for Ruby.
|
4
|
+
|
5
|
+
## Prerequisites
|
6
|
+
|
7
|
+
This gem requires *ImageMagick* to run. You can easily install it with *homebrew*:
|
8
|
+
|
9
|
+
```shell
|
10
|
+
brew update && brew install ImageMagick
|
11
|
+
```
|
12
|
+
|
13
|
+
## Install
|
14
|
+
|
15
|
+
Add this line to your Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'heatmap'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
bundle install
|
25
|
+
```
|
26
|
+
|
27
|
+
Or install it yourself:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
gem install heatmap
|
31
|
+
```
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Using `heatmap` is as easy as 1,2,3:
|
36
|
+
|
37
|
+
**1)** Create a new *Map* object:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
map = Heatmap.new #same as Heatmap::Map.new
|
41
|
+
```
|
42
|
+
|
43
|
+
**2)** Add *Area* objects to the map:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
map << Heatmap::Area.new(x, y, alpha)
|
47
|
+
```
|
48
|
+
|
49
|
+
**3)** Output the generated heatmap:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
map.output(filename)
|
53
|
+
```
|
54
|
+
|
55
|
+
## Example
|
56
|
+
|
57
|
+
Examples are included in the *examples* directory.
|
58
|
+
|
59
|
+
|
60
|
+
## Contributing to heatmap
|
61
|
+
|
62
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
63
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
64
|
+
* Fork the project.
|
65
|
+
* Start a feature/bugfix branch.
|
66
|
+
* Commit and push until you are happy with your contribution.
|
67
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
68
|
+
* Please try not to mess with the Rakefile, version, or history.
|
69
|
+
|
70
|
+
## Authors
|
71
|
+
|
72
|
+
* Thiago Jackiw: [@tjackiw](http://twitter.com/tjackiw)
|
73
|
+
|
74
|
+
## Copyright
|
75
|
+
|
76
|
+
Copyright (c) 2013 Thiago Jackiw. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'rake'
|
14
|
+
require 'jeweler'
|
15
|
+
|
16
|
+
$:.push File.expand_path("../lib", __FILE__)
|
17
|
+
require "heatmap/version"
|
18
|
+
|
19
|
+
Jeweler::Tasks.new do |gem|
|
20
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
21
|
+
gem.name = "heatmap"
|
22
|
+
gem.version = Heatmap::VERSION
|
23
|
+
gem.authors = ["Thiago Jackiw"]
|
24
|
+
gem.email = "tjackiw@gmail.com"
|
25
|
+
gem.homepage = "http://github.com/tjackiw/heatmap"
|
26
|
+
gem.license = "MIT"
|
27
|
+
gem.summary = %Q{ Heatmap generator in Ruby }
|
28
|
+
gem.description = %Q{ Simple Heatmap generator in Ruby. (Requires ImageMagick) }
|
29
|
+
gem.files = `git ls-files`.split("\n")
|
30
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
31
|
+
gem.require_paths = ["lib"]
|
32
|
+
end
|
33
|
+
Jeweler::RubygemsDotOrgTasks.new
|
34
|
+
|
35
|
+
require 'rake/testtask'
|
36
|
+
Rake::TestTask.new(:test) do |test|
|
37
|
+
test.libs << 'lib' << 'test'
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
39
|
+
test.verbose = true
|
40
|
+
end
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'yard'
|
45
|
+
YARD::Rake::YardocTask.new
|
data/examples/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
## Examples
|
2
|
+
|
3
|
+
### Simple example
|
4
|
+
|
5
|
+
Code:
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require 'heatmap'
|
9
|
+
|
10
|
+
map = Heatmap.new
|
11
|
+
map << Heatmap::Area.new(1, 10)
|
12
|
+
map << Heatmap::Area.new(5, 20)
|
13
|
+
map << Heatmap::Area.new(17, 10)
|
14
|
+
map << Heatmap::Area.new(25, 38)
|
15
|
+
map << Heatmap::Area.new(35, 70)
|
16
|
+
map << Heatmap::Area.new(15, 90)
|
17
|
+
map << Heatmap::Area.new(27, 60)
|
18
|
+
map.output('simple.png')
|
19
|
+
```
|
20
|
+
|
21
|
+
Output image:
|
22
|
+
|
23
|
+
![Simple](simple.png)
|
24
|
+
|
25
|
+
### External data example
|
26
|
+
|
27
|
+
Code:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'json'
|
31
|
+
require 'heatmap'
|
32
|
+
|
33
|
+
data = open('large-data').read
|
34
|
+
map = Heatmap.new
|
35
|
+
|
36
|
+
data.split(/\n/).each do |point|
|
37
|
+
point = JSON.parse(point)
|
38
|
+
map << Heatmap::Area.new(*point.values)
|
39
|
+
end
|
40
|
+
|
41
|
+
map.output('large.png')
|
42
|
+
```
|
43
|
+
|
44
|
+
Output image:
|
45
|
+
|
46
|
+
![Simple](large.png)
|
data/examples/large-data
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
{"x":174, "y":158, "alpha":0.20327458219046335}
|
2
|
+
{"x":72, "y":154, "alpha":0.7998730751649824}
|
3
|
+
{"x":233, "y":66, "alpha":0.5900612301366825}
|
4
|
+
{"x":156, "y":104, "alpha":0.9202633639717721}
|
5
|
+
{"x":115, "y":111, "alpha":0.688794841564036}
|
6
|
+
{"x":68, "y":143, "alpha":0.9888723603164732}
|
7
|
+
{"x":147, "y":103, "alpha":0.29725895228191923}
|
8
|
+
{"x":141, "y":8, "alpha":0.21369779927798993}
|
9
|
+
{"x":181, "y":160, "alpha":0.4225620916108723}
|
10
|
+
{"x":240, "y":142, "alpha":0.3281368093602379}
|
11
|
+
{"x":227, "y":18, "alpha":0.42324181963722607}
|
12
|
+
{"x":46, "y":132, "alpha":0.6441184493358745}
|
13
|
+
{"x":181, "y":145, "alpha":0.45815362337810606}
|
14
|
+
{"x":182, "y":191, "alpha":0.5309734278169269}
|
15
|
+
{"x":213, "y":142, "alpha":0.2801929544657056}
|
16
|
+
{"x":212, "y":181, "alpha":0.12582499834939836}
|
17
|
+
{"x":57, "y":55, "alpha":0.5934894632055536}
|
18
|
+
{"x":220, "y":200, "alpha":0.7841007273290707}
|
19
|
+
{"x":60, "y":6, "alpha":0.850718863406586}
|
20
|
+
{"x":143, "y":169, "alpha":0.6644476863208374}
|
21
|
+
{"x":103, "y":163, "alpha":0.42830694157085025}
|
22
|
+
{"x":61, "y":179, "alpha":0.8616324825322345}
|
23
|
+
{"x":0, "y":57, "alpha":0.9972641715363543}
|
24
|
+
{"x":249, "y":32, "alpha":0.23658539370469378}
|
25
|
+
{"x":98, "y":142, "alpha":0.9310884298373363}
|
26
|
+
{"x":207, "y":17, "alpha":0.3427204846193057}
|
27
|
+
{"x":136, "y":144, "alpha":0.9212137584718184}
|
28
|
+
{"x":61, "y":63, "alpha":0.6725635254452301}
|
29
|
+
{"x":49, "y":67, "alpha":0.19678745642065965}
|
30
|
+
{"x":248, "y":153, "alpha":0.837363034506756}
|
31
|
+
{"x":143, "y":135, "alpha":0.7454935580837386}
|
32
|
+
{"x":167, "y":133, "alpha":0.26496853463366554}
|
33
|
+
{"x":43, "y":156, "alpha":0.9515808378024672}
|
34
|
+
{"x":81, "y":175, "alpha":0.3191620399224552}
|
35
|
+
{"x":127, "y":188, "alpha":0.948854598961451}
|
36
|
+
{"x":101, "y":84, "alpha":0.2890309609453612}
|
37
|
+
{"x":165, "y":106, "alpha":0.7433647743986191}
|
38
|
+
{"x":116, "y":12, "alpha":0.3352071384993661}
|
39
|
+
{"x":237, "y":71, "alpha":0.17069755686114352}
|
40
|
+
{"x":128, "y":55, "alpha":0.5602446574209351}
|
41
|
+
{"x":16, "y":147, "alpha":0.4705393402165682}
|
42
|
+
{"x":85, "y":79, "alpha":0.7838664058016899}
|
43
|
+
{"x":229, "y":98, "alpha":0.6387269857871185}
|
44
|
+
{"x":143, "y":4, "alpha":0.34247034282873456}
|
45
|
+
{"x":195, "y":192, "alpha":0.15840369607987567}
|
46
|
+
{"x":111, "y":133, "alpha":0.3484817073844113}
|
47
|
+
{"x":54, "y":32, "alpha":0.4357294527937766}
|
48
|
+
{"x":80, "y":46, "alpha":0.5528598869173067}
|
49
|
+
{"x":237, "y":167, "alpha":0.4793169054851376}
|
50
|
+
{"x":237, "y":166, "alpha":0.6034214381668269}
|
data/examples/large.png
ADDED
Binary file
|
data/examples/large.rb
ADDED
data/examples/simple.png
ADDED
Binary file
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'heatmap'
|
2
|
+
|
3
|
+
map = Heatmap.new
|
4
|
+
map << Heatmap::Area.new(1, 10)
|
5
|
+
map << Heatmap::Area.new(5, 20)
|
6
|
+
map << Heatmap::Area.new(17, 10)
|
7
|
+
map << Heatmap::Area.new(25, 38)
|
8
|
+
map << Heatmap::Area.new(35, 70)
|
9
|
+
map << Heatmap::Area.new(15, 90)
|
10
|
+
map << Heatmap::Area.new(27, 60)
|
11
|
+
map.output('simple.png')
|
data/heatmap.gemspec
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "heatmap"
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Thiago Jackiw"]
|
12
|
+
s.date = "2013-01-24"
|
13
|
+
s.description = " Simple Heatmap generator in Ruby. (Requires ImageMagick) "
|
14
|
+
s.email = "tjackiw@gmail.com"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.md"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
".travis.yml",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.md",
|
27
|
+
"Rakefile",
|
28
|
+
"examples/README.md",
|
29
|
+
"examples/large-data",
|
30
|
+
"examples/large.png",
|
31
|
+
"examples/large.rb",
|
32
|
+
"examples/simple.png",
|
33
|
+
"examples/simple.rb",
|
34
|
+
"heatmap.gemspec",
|
35
|
+
"lib/assets/gradient.png",
|
36
|
+
"lib/assets/point.png",
|
37
|
+
"lib/heatmap.rb",
|
38
|
+
"lib/heatmap/area.rb",
|
39
|
+
"lib/heatmap/geometry.rb",
|
40
|
+
"lib/heatmap/image.rb",
|
41
|
+
"lib/heatmap/map.rb",
|
42
|
+
"lib/heatmap/version.rb",
|
43
|
+
"test/helper.rb",
|
44
|
+
"test/test_area.rb",
|
45
|
+
"test/test_geometry.rb",
|
46
|
+
"test/test_heatmap.rb",
|
47
|
+
"test/test_image.rb",
|
48
|
+
"test/test_map.rb"
|
49
|
+
]
|
50
|
+
s.homepage = "http://github.com/tjackiw/heatmap"
|
51
|
+
s.licenses = ["MIT"]
|
52
|
+
s.require_paths = ["lib"]
|
53
|
+
s.rubygems_version = "1.8.24"
|
54
|
+
s.summary = "Heatmap generator in Ruby"
|
55
|
+
s.test_files = ["test/helper.rb", "test/test_area.rb", "test/test_geometry.rb", "test/test_heatmap.rb", "test/test_image.rb", "test/test_map.rb"]
|
56
|
+
|
57
|
+
if s.respond_to? :specification_version then
|
58
|
+
s.specification_version = 3
|
59
|
+
|
60
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
61
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
62
|
+
s.add_development_dependency(%q<yard>, ["~> 0.7"])
|
63
|
+
s.add_development_dependency(%q<bundler>, [">= 0"])
|
64
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
67
|
+
s.add_dependency(%q<yard>, ["~> 0.7"])
|
68
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
69
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
70
|
+
end
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
73
|
+
s.add_dependency(%q<yard>, ["~> 0.7"])
|
74
|
+
s.add_dependency(%q<bundler>, [">= 0"])
|
75
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
Binary file
|
Binary file
|
data/lib/heatmap/area.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Heatmap
|
2
|
+
class Area
|
3
|
+
|
4
|
+
attr_reader :x,:y, :alpha
|
5
|
+
|
6
|
+
def initialize(x, y, alpha = 1)
|
7
|
+
raise(ArgumentError, "The x, y, alpha values need to be >= 0") if x < 0 || y < 0 || alpha < 0
|
8
|
+
@x, @y, @alpha = x, y, alpha
|
9
|
+
end
|
10
|
+
|
11
|
+
def x_y
|
12
|
+
"+#{x}+#{y}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Heatmap
|
4
|
+
class Geometry < OpenStruct
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def bounds(area, point_image_width)
|
8
|
+
raise(ArgumentError, "Area needs to be an array of Heatmap::Area objects") if area.empty?
|
9
|
+
|
10
|
+
@area = area
|
11
|
+
new(width: point_image_width + max_x, height: point_image_width + max_y)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def max_x
|
16
|
+
@area.max{|a,b| a.x <=> b.x }.x
|
17
|
+
end
|
18
|
+
|
19
|
+
def max_y
|
20
|
+
@area.max{|a,b| a.y <=> b.y }.y
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Heatmap
|
2
|
+
class Image
|
3
|
+
|
4
|
+
POINT = File.new(File.dirname(__FILE__) + "/../assets/point.png", 'r')
|
5
|
+
GRADIENT = File.new(File.dirname(__FILE__) + "/../assets/gradient.png", 'r')
|
6
|
+
|
7
|
+
def initialize(area, file)
|
8
|
+
raise(ArgumentError, "Area needs to be an array of Heatmap::Area objects") if area.empty?
|
9
|
+
|
10
|
+
file = File.new(file, 'w')
|
11
|
+
bounds = Heatmap::Geometry.bounds(area, 100)
|
12
|
+
|
13
|
+
# Creating a blank canvas
|
14
|
+
system("convert -size #{bounds.width}x#{bounds.height} pattern:gray100 #{file.path}")
|
15
|
+
|
16
|
+
# Drawing each area
|
17
|
+
compose = ["convert #{file.path}"]
|
18
|
+
compose << area.map{|area| "-page #{area.x_y} #{POINT.path}" }
|
19
|
+
compose << "-layers flatten #{file.path}"
|
20
|
+
system(compose * ' ')
|
21
|
+
|
22
|
+
# Applying color with a LUT
|
23
|
+
system("convert -channel ALL -clut #{file.path} #{GRADIENT.path} #{file.path}")
|
24
|
+
|
25
|
+
# Apply a default 50% opacity
|
26
|
+
system("mogrify -channel A -fx \"A*0.50\" #{file.path}")
|
27
|
+
|
28
|
+
file.close
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/heatmap/map.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Heatmap
|
2
|
+
class Map
|
3
|
+
|
4
|
+
attr_accessor :area
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
raise(RuntimeError, "You need to have ImageMagick installed!") if `which convert`.strip.empty?
|
8
|
+
@area = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def <<(item)
|
12
|
+
@area << item
|
13
|
+
end
|
14
|
+
|
15
|
+
def output(file = 'heatmap.png')
|
16
|
+
Heatmap::Image.new(@area, file)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/lib/heatmap.rb
ADDED
data/test/helper.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'heatmap'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
File.unlink(example_png_file) if File.exists?(example_png_file)
|
21
|
+
end
|
22
|
+
|
23
|
+
def example_png_file
|
24
|
+
File.dirname(__FILE__) + "/example.png"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
data/test/test_area.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestArea < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "initialize the class" do
|
6
|
+
assert Heatmap::Area === Heatmap::Area.new(1,1,0.5)
|
7
|
+
end
|
8
|
+
|
9
|
+
should "fail to initialize on values less than zero" do
|
10
|
+
[ {x: -1, y: 1, a: 0.5}, {x: 1, y: -1, a: 0.5}, {x: 1, y: 1, a: -1}].each do |set|
|
11
|
+
assert_raise ArgumentError do
|
12
|
+
Heatmap::Area.new(*set.values)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
should "be able to access to instance values" do
|
18
|
+
x, y, a = 1, 2, 0.5
|
19
|
+
area = Heatmap::Area.new(x, y, a)
|
20
|
+
assert_equal x, area.x
|
21
|
+
assert_equal y, area.y
|
22
|
+
assert_equal a, area.alpha
|
23
|
+
end
|
24
|
+
|
25
|
+
should "return the x_y values" do
|
26
|
+
area = Heatmap::Area.new(10, 100)
|
27
|
+
assert_equal "+10+100", area.x_y
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestGeometry < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "properly generate the image bounds" do
|
6
|
+
area = [Heatmap::Area.new(1,10), Heatmap::Area.new(10,20)]
|
7
|
+
bounds = Heatmap::Geometry.bounds(area, 50)
|
8
|
+
assert_equal 60, bounds.width
|
9
|
+
assert_equal 70, bounds.height
|
10
|
+
end
|
11
|
+
|
12
|
+
should "properly generate the image bounds with one element" do
|
13
|
+
area = [Heatmap::Area.new(1,10)]
|
14
|
+
bounds = Heatmap::Geometry.bounds(area, 50)
|
15
|
+
assert_equal 51, bounds.width
|
16
|
+
assert_equal 60, bounds.height
|
17
|
+
end
|
18
|
+
|
19
|
+
should "properly generate the image bounds in hypothetical negative image width" do
|
20
|
+
area = [Heatmap::Area.new(1,10), Heatmap::Area.new(10,20)]
|
21
|
+
bounds = Heatmap::Geometry.bounds(area, -50)
|
22
|
+
assert_equal -40, bounds.width
|
23
|
+
assert_equal -30, bounds.height
|
24
|
+
end
|
25
|
+
|
26
|
+
should "raise exception when area is empty" do
|
27
|
+
area = []
|
28
|
+
assert_raise ArgumentError do
|
29
|
+
Heatmap::Geometry.bounds(area, 10)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/test/test_image.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestImage < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "fail to instantiate the class due to empty area" do
|
6
|
+
assert_raise ArgumentError do
|
7
|
+
Heatmap::Image.new([], example_png_file)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
# TODO: improve this test
|
12
|
+
should "properly instantiate the class" do
|
13
|
+
area = [Heatmap::Area.new(1,2)]
|
14
|
+
assert Heatmap::Image === Heatmap::Image.new(area, example_png_file)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/test/test_map.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestMap < Test::Unit::TestCase
|
4
|
+
|
5
|
+
should "properly instantiate the class" do
|
6
|
+
assert Heatmap::Map === Heatmap::Map.new
|
7
|
+
end
|
8
|
+
|
9
|
+
should "properly output the image" do
|
10
|
+
map = Heatmap::Map.new
|
11
|
+
map << Heatmap::Area.new(1, 2)
|
12
|
+
map.area << Heatmap::Area.new(3, 4)
|
13
|
+
assert map.output(example_png_file)
|
14
|
+
end
|
15
|
+
|
16
|
+
should "fail to output on empty area array" do
|
17
|
+
map = Heatmap::Map.new
|
18
|
+
assert_raise ArgumentError do
|
19
|
+
map.output
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: heatmap
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Thiago Jackiw
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: shoulda
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: yard
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.7'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.7'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: jeweler
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.8.4
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 1.8.4
|
78
|
+
description: ! ' Simple Heatmap generator in Ruby. (Requires ImageMagick) '
|
79
|
+
email: tjackiw@gmail.com
|
80
|
+
executables: []
|
81
|
+
extensions: []
|
82
|
+
extra_rdoc_files:
|
83
|
+
- LICENSE.txt
|
84
|
+
- README.md
|
85
|
+
files:
|
86
|
+
- .document
|
87
|
+
- .gitignore
|
88
|
+
- .travis.yml
|
89
|
+
- Gemfile
|
90
|
+
- Gemfile.lock
|
91
|
+
- LICENSE.txt
|
92
|
+
- README.md
|
93
|
+
- Rakefile
|
94
|
+
- examples/README.md
|
95
|
+
- examples/large-data
|
96
|
+
- examples/large.png
|
97
|
+
- examples/large.rb
|
98
|
+
- examples/simple.png
|
99
|
+
- examples/simple.rb
|
100
|
+
- heatmap.gemspec
|
101
|
+
- lib/assets/gradient.png
|
102
|
+
- lib/assets/point.png
|
103
|
+
- lib/heatmap.rb
|
104
|
+
- lib/heatmap/area.rb
|
105
|
+
- lib/heatmap/geometry.rb
|
106
|
+
- lib/heatmap/image.rb
|
107
|
+
- lib/heatmap/map.rb
|
108
|
+
- lib/heatmap/version.rb
|
109
|
+
- test/helper.rb
|
110
|
+
- test/test_area.rb
|
111
|
+
- test/test_geometry.rb
|
112
|
+
- test/test_heatmap.rb
|
113
|
+
- test/test_image.rb
|
114
|
+
- test/test_map.rb
|
115
|
+
homepage: http://github.com/tjackiw/heatmap
|
116
|
+
licenses:
|
117
|
+
- MIT
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ! '>='
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
version: '0'
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
hash: -2057164444541069144
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 1.8.24
|
140
|
+
signing_key:
|
141
|
+
specification_version: 3
|
142
|
+
summary: Heatmap generator in Ruby
|
143
|
+
test_files:
|
144
|
+
- test/helper.rb
|
145
|
+
- test/test_area.rb
|
146
|
+
- test/test_geometry.rb
|
147
|
+
- test/test_heatmap.rb
|
148
|
+
- test/test_image.rb
|
149
|
+
- test/test_map.rb
|