rubicus 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,6 @@
1
+ = Rubicus Changelog
2
+
3
+ == Version 0.1.0
4
+ (August 24th, 2006)
5
+
6
+ * Initial release.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006 Jonathan Younger (jonathan@daikini.com)
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 ADDED
@@ -0,0 +1,11 @@
1
+ ==Rubicus
2
+
3
+ Author:: Jonathan Younger (jonathan@daikini.com)
4
+ Date:: August 24th, 2006
5
+
6
+ Rubicus is a pure Ruby wrapper around the ploticus http://ploticus.sourceforge.net graphing library.
7
+
8
+ For basic usage instructions, refer to the documentation for Rubicus::Graph.
9
+
10
+ Based on the design of Scruffy Graphs (a beautiful graphing library for Ruby) by Brasten Sager. http://scruffy.rubyforge.org/
11
+ Custom ploticus graph code taken from ploticus.rb by Mike Neumann. http://www.ntecs.de/blog-old/Blog/RubyPloticus.rdoc
@@ -0,0 +1,84 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/contrib/rubyforgepublisher'
8
+ require 'lib/rubicus'
9
+
10
+ PKG_NAME = "rubicus"
11
+ PKG_VERSION = Rubicus::VERSION
12
+ PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
13
+ PKG_FILES = FileList[
14
+ '[A-Z]*',
15
+ 'lib/**/*.rb',
16
+ 'test/**/*.rb'
17
+ ]
18
+
19
+ desc "Deploy docs to RubyForge"
20
+ task :rdoc_deploy => [:rdoc] do
21
+ dirs = %w{doc}
22
+ onserver = "poogle@rubyforge.org:/var/www/gforge-projects/rubicus"
23
+ dirs.each do | dir|
24
+ `scp -r "#{`pwd`.chomp}/#{dir}" "#{onserver}"`
25
+ end
26
+ end
27
+
28
+ # Genereate the RDoc documentation
29
+ Rake::RDocTask.new { |rdoc|
30
+ rdoc.rdoc_dir = 'doc'
31
+ rdoc.title = "Rubicus - Graphing Library for Ruby using the ploticus backend."
32
+ rdoc.rdoc_files.include("README", "CHANGELOG", "MIT-LICENSE")
33
+ rdoc.rdoc_files.include("lib/rubicus.rb")
34
+ rdoc.rdoc_files.include("lib/rubicus/*.rb")
35
+ rdoc.rdoc_files.include("lib/rubicus/layers/*.rb")
36
+ }
37
+
38
+ spec = Gem::Specification.new do |s|
39
+ s.name = PKG_NAME
40
+ s.version = PKG_VERSION
41
+ s.author = "Jonathan Younger"
42
+ s.email = "jonathan@daikini.com"
43
+ s.homepage = "http://rubicus.rubyforge.org"
44
+ s.summary = "Graphing library for Ruby using the ploticus backend."
45
+ s.description = "Rubicus is a pure Ruby wrapper around the ploticus http://ploticus.sourceforge.net graphing library."
46
+ s.files = PKG_FILES.to_a
47
+ s.has_rdoc = false
48
+ s.rubyforge_project = "rubicus"
49
+ end
50
+
51
+ Rake::GemPackageTask.new(spec) do |pkg|
52
+ pkg.need_zip = true
53
+ pkg.need_tar = true
54
+ end
55
+
56
+ task :verify_user do
57
+ raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER']
58
+ end
59
+
60
+ task :verify_password do
61
+ raise "RUBYFORGE_PASSWORD environment variable not set!" unless ENV['RUBYFORGE_PASSWORD']
62
+ end
63
+
64
+ desc "Publish gem+tgz+zip on RubyForge. You must make sure lib/version.rb is aligned with the CHANGELOG file"
65
+ task :publish_packages => [:verify_user, :verify_password, :package] do
66
+ require 'meta_project'
67
+ require 'rake/contrib/xforge'
68
+ release_files = FileList[
69
+ "pkg/#{PKG_FILE_NAME}.gem",
70
+ "pkg/#{PKG_FILE_NAME}.tgz",
71
+ "pkg/#{PKG_FILE_NAME}.zip",
72
+ "pkg/#{PKG_FILE_NAME}.gem.md5",
73
+ "pkg/#{PKG_FILE_NAME}.tgz.md5",
74
+ "pkg/#{PKG_FILE_NAME}.zip.md5"
75
+ ]
76
+
77
+ Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PKG_NAME)) do |xf|
78
+ # Never hardcode user name and password in the Rakefile!
79
+ xf.user_name = ENV['RUBYFORGE_USER']
80
+ xf.password = ENV['RUBYFORGE_PASSWORD']
81
+ xf.files = release_files.to_a
82
+ xf.release_name = "Rubicus #{PKG_VERSION}"
83
+ end
84
+ end
@@ -0,0 +1,8 @@
1
+ module Rubicus; end
2
+
3
+ $:.unshift(File.dirname(__FILE__)) unless
4
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
5
+
6
+ require 'rubicus/version'
7
+ require 'rubicus/graph'
8
+ require 'rubicus/layers'
@@ -0,0 +1,125 @@
1
+ require 'tempfile'
2
+
3
+ module Rubicus
4
+
5
+ # ==Rubicus Graph
6
+ #
7
+ # Author:: Jonathan Younger
8
+ # Date:: August 24th, 2006
9
+ #
10
+ #
11
+ # ====Graphs vs. Layers (Graph Types)
12
+ #
13
+ # Rubicus::Graph is the primary class you will use to generate your graphs. A Graph does not
14
+ # define a graph type nor does it directly hold any data. Instead, a Graph object can be thought
15
+ # of as a canvas on which other graphs are draw. (The actual graphs themselves are subclasses of Rubicus::Layers::Base)
16
+ # Despite the technical distinction, we will refer to Rubicus::Graph objects as 'graphs' and Rubicus::Layers as
17
+ # 'layers' or 'graph types.'
18
+ #
19
+ #
20
+ # ==== Creating a Graph
21
+ #
22
+ # You can begin building a graph by instantiating a Graph object
23
+ #
24
+ # graph = Rubicus::Graph.new
25
+ #
26
+ # Once you have a Graph object you can begin adding graph layers.
27
+ # You can add a graph layer to a graph by using the Graph#add or Graph#<< methods.
28
+ # The two methods are identical and used to accommodate syntax preferences.
29
+ #
30
+ # graph.add :lines, [[10, 20], [20, 30], [30, 40], [40, 50]], :title => "Jack", :x => 1, :y => 2, :pointsym => :none, :rectangle => [1, 1, 3, 3]
31
+ # graph.add :lines, [[10, 20], [20, 30], [30, 40], [40, 50]], :title => "Jill", :x => 1, :y => 2, :pointsym => :none, :rectangle => [4, 1, 6, 3]
32
+ #
33
+ # Now that we've created our graph and added a layer to it, we're ready to render! You can render the graph
34
+ # directly to PNG or any other image format (supported by ploticus) with the Graph#render method:
35
+ #
36
+ # # Defaults to PNG
37
+ # graph.render
38
+ #
39
+ # # For image formats other than PNG:
40
+ # graph.render(:as => 'GIF')
41
+ #
42
+ # # To render directly to a file:
43
+ # graph.render(:to => '<filename>')
44
+ #
45
+ # graph.render(:as => 'GIF', :to => '<filename>')
46
+ #
47
+ # And that's your basic Rubicus graph! Please check the ploticus documentation for the various methods and
48
+ # classes you'll be using, as there are a bunch of options not demonstrated here.
49
+ #
50
+ # A couple final things worth noting:
51
+ # * You can call Graph#render as often as you wish with different rendering options. In
52
+ # fact, you can modify the graph any way you wish between renders.
53
+ #
54
+ #
55
+ # * There are no restrictions to the combination of graph layers you can add. It is perfectly
56
+ # valid to do something like:
57
+ # graph.add(:lines, [100, 200, 300])
58
+ # graph.add(:vbars, [200, 150, 150])
59
+ class Graph
60
+ attr_accessor :layers
61
+ attr_accessor :default_type
62
+ attr_accessor :options
63
+
64
+ def initialize(options = {})
65
+ @default_type = options.delete(:type)
66
+ @options = options
67
+ @layers ||= []
68
+ end
69
+
70
+ def <<(*args, &block)
71
+ if args[0].kind_of?(Rubicus::Layers::Base)
72
+ layers << args[0]
73
+ else
74
+ type = args.first.is_a?(Symbol) ? args.shift : @default_type
75
+ data = args.first.is_a?(Array) ? args.shift : []
76
+ options = args.first.is_a?(Hash) ? args.shift : {}
77
+
78
+ raise ArgumentError, "You must specify a graph type (:scat, :lines, :pie, etc) if you do not have a default type specified." if type.nil?
79
+
80
+ unless Rubicus::Layers.const_defined? to_camelcase(type.to_s)
81
+ layer = Rubicus::Layers::Prefab.new(options.merge({ :prefab => type, :data => data }))
82
+ else
83
+ layer = Kernel::module_eval("Rubicus::Layers::#{to_camelcase(type.to_s)}").new(options.merge({ :data => data }), &block)
84
+ end
85
+
86
+ layers << layer
87
+ end
88
+ layer
89
+ end
90
+
91
+ alias :add :<<
92
+
93
+ # Renders the graph in it's current state to an PNG object.
94
+ #
95
+ # Options:
96
+ # as:: File format to render to ('PNG', 'JPG', etc)
97
+ # to:: Name of file to save graph to, if desired. If not provided, image is returned as blob/string.
98
+ def render(options = {})
99
+ options[:o] ||= "stdout"
100
+ image_type = options.delete(:as) || "png"
101
+ to = options.delete(:to)
102
+
103
+ image = case layers.size
104
+ when 0
105
+ raise "You haven't specified any layers to render."
106
+ when 1
107
+ layers.first.draw(image_type, @options.merge(options))
108
+ else
109
+ dump_file = Tempfile.new("rubicus_dump_file")
110
+ layers.each { |layer| layer.draw(nil, :drawdumpa => dump_file.path) }
111
+ layer = Rubicus::Layers::Prefab.new(:prefab => :draw, :dumpfile => dump_file.path)
112
+ layer.draw(image_type, @options.merge(options))
113
+ end
114
+
115
+ File.open(to, "w") { |file| file.write(image) } if to
116
+
117
+ image
118
+ end
119
+
120
+ protected
121
+ def to_camelcase(type) # :nodoc:
122
+ type.split("_").map { |e| e.capitalize }.join("")
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubicus/layers/base'
2
+ require 'rubicus/layers/custom'
3
+ require 'rubicus/layers/prefab'
@@ -0,0 +1,46 @@
1
+ module Rubicus::Layers
2
+ class Base
3
+ protected
4
+ def convert_options(obj)
5
+ case obj
6
+ when String
7
+ obj.gsub("\n", "\\n")
8
+ when Array
9
+ if obj[0].kind_of? Array
10
+ obj.map { |row| row.join(" ") }.join
11
+ else
12
+ obj.join(" ")
13
+ end
14
+ when Hash
15
+ obj.map { |k,v| "#{k}=#{convert_options(v)}" }.join(" ")
16
+ when true
17
+ 'yes'
18
+ when false
19
+ 'no'
20
+ else
21
+ obj.to_s
22
+ end
23
+ end
24
+
25
+ def convert(obj)
26
+ case obj
27
+ when String
28
+ obj.gsub("\n", "\\n") + "\n"
29
+ when Array
30
+ if obj[0].kind_of? Array
31
+ obj.map {|row| row.join(" ") + "\n"}.join
32
+ else
33
+ obj.join(" ")
34
+ end
35
+ when Hash
36
+ obj.map {|k,v| "#{ k }=#{ convert(v) }" }.join(" ")
37
+ when true
38
+ 'yes'
39
+ when false
40
+ 'no'
41
+ else
42
+ obj.to_s
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,68 @@
1
+ # Most of this code is from the ploticus.rb file by Mike Neumann http://www.ntecs.de/blog-old/Blog/RubyPloticus.rdoc
2
+
3
+ module Rubicus::Layers
4
+ class Custom < Base
5
+ def initialize
6
+ reset!
7
+ end
8
+
9
+ def data=(rows)
10
+ data {|a| a.data = rows }
11
+ end
12
+
13
+ def draw(image_type = "png", options = {})
14
+ options[image_type] = nil if image_type
15
+ ploticus_options = options.map { |key, option| "-#{key} #{convert_options(option)}" }.join(" ")
16
+ io = IO.popen("ploticus -stdin #{ploticus_options}", "w+")
17
+ io.write @s
18
+ io.close_write
19
+ img = io.read
20
+ io.close
21
+ img
22
+ end
23
+
24
+ def reset!
25
+ @s = ""
26
+ end
27
+
28
+ PROCS = [
29
+ [:data, :getdata],
30
+ [:area, :areadef],
31
+ ]
32
+
33
+ PROCS.each do |m, mp|
34
+ mp ||= m
35
+ eval %[ def #{ m }(&block) do_block("#{ mp }", &block) end ]
36
+ end
37
+
38
+ def method_missing(id, &block)
39
+ do_block(id.to_s, &block)
40
+ end
41
+
42
+ private
43
+ def do_block(mp, &block)
44
+ @s << "#proc #{ mp }\n"
45
+ AttrWriter.new(&block).__attrs__.each do |k, v|
46
+ @s << "#{ k }: #{ convert(v) }\n"
47
+ end
48
+ @s << "\n"
49
+ end
50
+
51
+ class AttrWriter
52
+ instance_methods.each { |m| undef_method m unless m =~ /^__/ }
53
+
54
+ def __attrs__
55
+ @attrs
56
+ end
57
+
58
+ def initialize(&block)
59
+ @attrs = {}
60
+ block.call(self)
61
+ end
62
+
63
+ def method_missing(id, value)
64
+ @attrs[id.to_s.gsub("=", "")] = value
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,49 @@
1
+ module Rubicus::Layers
2
+ class Prefab < Base
3
+ def initialize(options = {})
4
+ @type = options.delete(:prefab)
5
+ @data = options.delete(:data)
6
+ @options = options
7
+ @options[:delim] ||= :comma
8
+ end
9
+
10
+ def draw(image_type = "png", options = {})
11
+ options[image_type] = nil if image_type
12
+ options[:prefab] ||= @type
13
+
14
+ if @data
15
+ data = if @data[0].kind_of? Array
16
+ @data.map {|row| row.join(delimiter_for_delim(@options[:delim])) }.join("\n")
17
+ else
18
+ @data.join(",")
19
+ end
20
+ else
21
+ data = nil
22
+ end
23
+
24
+ ploticus_options = options.map { |key, option| "-#{key} #{convert_options(option)}" }.join(" ")
25
+ prefab_options = @options.map { |key, option| "#{key}=\"#{convert_options(option)}\"" }.join(" ")
26
+ io = IO.popen("ploticus #{@data ? "data=stdin" : ""} #{ploticus_options} #{prefab_options}", "w+")
27
+ if @data
28
+ io.write data
29
+ io.close_write
30
+ end
31
+ img = io.read
32
+ io.close
33
+ img
34
+ end
35
+
36
+
37
+ protected
38
+ def delimiter_for_delim(delim)
39
+ case delim
40
+ when :comma
41
+ ","
42
+ when :tab
43
+ "\t"
44
+ else
45
+ " "
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Rubicus
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,131 @@
1
+ #/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../lib/rubicus'
3
+
4
+ data = [
5
+ ["Name", "Concentration", "PeakArea"],
6
+ ["A", 1, 2],
7
+ ["B", 2, 3],
8
+ ["C", 2, 4],
9
+ ["D", 1, 4],
10
+ ["E", 6, 7]
11
+ ]
12
+
13
+ # layer = Rubicus::Layers::Scat.new(:data => data, :xgrid => { :width => "0.1", :color => "gray(0.9)"}, :x => 2, :y => 3, :corr => true)
14
+
15
+ g = Rubicus::Graph.new
16
+ g.add :scat, data, :xgrid => { :width => "0.1", :color => "gray(0.9)" }, :x => 2, :y => 3, :corr => true, :rectangle => [1, 1, 3, 3]
17
+ g.add :scat, data, :xgrid => { :width => "0.6", :color => "gray(2.5)" }, :x => 2, :y => 3, :corr => true, :rectangle => [4, 1, 6, 3]
18
+ # g.add layer
19
+ g.render(:to => "bob.png")
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+ layer = Rubicus::Layers::Custom.new
48
+
49
+ layer.data = [
50
+ [2000, 750],
51
+ [2010, 1700],
52
+ [2015, 2000],
53
+ [2020, 1800],
54
+ [2025, 1300],
55
+ [2030, 400]
56
+ ]
57
+
58
+ layer.area {|a|
59
+ a.title = "Social Security trust fund asset estimates, in $ billions\nhallo\nsuper"
60
+ a.titledetails = {:adjust => "0,0.1"}
61
+ a.rectangle = [1, 1, 5, 2]
62
+ a.xrange = [2000, 2035]
63
+ a.yrange = [0, 2000]
64
+ }
65
+
66
+ layer.xaxis {|a|
67
+ a.stubs = "inc 5"
68
+ a.label = "Year"
69
+ }
70
+
71
+ layer.lineplot {|a|
72
+ a.xfield = 1
73
+ a.yfield = 2
74
+ a.fill = "pink"
75
+ }
76
+
77
+ layer.lineplot {|a|
78
+ a.xfield = 1
79
+ a.yfield = 2
80
+ a.fill = "rgb(.7,.3,.3)"
81
+ a.linerange = [2010, 2020]
82
+ }
83
+
84
+ layer.lineplot {|a|
85
+ a.xfield = 1
86
+ a.yfield = 2
87
+ a.linedetails = {:color => 'red'}
88
+ a.fill = "rgb(.7,.3,.3)"
89
+ a.linerange = [2010, 2020]
90
+ }
91
+
92
+ layer.yaxis {|a|
93
+ a.stubs = "incremental 500"
94
+ a.grid = {:color=> 'blue'}
95
+ a.axisline = 'none'
96
+ }
97
+
98
+ g = Rubicus::Graph.new
99
+ g.add layer
100
+ g.render(:to => "bob2.png")
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+ g = Rubicus::Graph.new
110
+ g.add :lines, [[10, 20], [20, 30], [30, 40], [40, 50]], :title => "Jack", :x => 1, :y => 2, :pointsym => :none, :rectangle => [1, 1, 3, 3]
111
+ g.add :lines, [[10, 20], [20, 30], [30, 40], [40, 50]], :title => "Jill", :x => 1, :y => 2, :pointsym => :none, :rectangle => [4, 1, 6, 3]
112
+ g.render :to => "hmm.png"
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+ data = (1..12).collect { |i| ["Test #{i}", rand(110), rand(20)] }
121
+
122
+ g = Rubicus::Graph.new
123
+ g.add :vbars, data, :x => 1, :y => 2, :autow => false, :errunder => true, :ygrid => true, :barwidth => :line, :stubvert => true, :xaxis => :none, :yaxis => :none, :rectangle => [0, 0, 0.5, 0.2], :legend => false, :header => false, :yrange => 110
124
+ g.render(:to => "sweet.png")
125
+
126
+
127
+ # data = (1..12).collect { |i| [i, rand(20)] }
128
+ #
129
+ # g = Rubicus::Graph.new
130
+ # g.add :line, data, :x => 1, :y => 2, :pointsym => :none, :xaxis => :none
131
+ # g.render(:to => "sweet.png")
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: rubicus
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.1.0
7
+ date: 2006-08-30 00:00:00 -07:00
8
+ summary: Graphing library for Ruby using the ploticus backend.
9
+ require_paths:
10
+ - lib
11
+ email: jonathan@daikini.com
12
+ homepage: http://rubicus.rubyforge.org
13
+ rubyforge_project: rubicus
14
+ description: Rubicus is a pure Ruby wrapper around the ploticus http://ploticus.sourceforge.net graphing library.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Jonathan Younger
31
+ files:
32
+ - CHANGES
33
+ - MIT-LICENSE
34
+ - Rakefile
35
+ - README
36
+ - lib/rubicus.rb
37
+ - lib/rubicus/graph.rb
38
+ - lib/rubicus/layers.rb
39
+ - lib/rubicus/version.rb
40
+ - lib/rubicus/layers/base.rb
41
+ - lib/rubicus/layers/custom.rb
42
+ - lib/rubicus/layers/prefab.rb
43
+ - test/test.rb
44
+ test_files: []
45
+
46
+ rdoc_options: []
47
+
48
+ extra_rdoc_files: []
49
+
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ requirements: []
55
+
56
+ dependencies: []
57
+