gruff 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
Binary file
data/lib/gruff.rb CHANGED
@@ -7,3 +7,4 @@ require File.dirname(__FILE__) + '/gruff/area'
7
7
  require File.dirname(__FILE__) + '/gruff/bar'
8
8
  require File.dirname(__FILE__) + '/gruff/line'
9
9
  require File.dirname(__FILE__) + '/gruff/pie'
10
+ require File.dirname(__FILE__) + '/gruff/stacked_bar'
data/lib/gruff/base.rb CHANGED
@@ -7,17 +7,13 @@
7
7
  #
8
8
  #
9
9
 
10
- begin
11
- require 'rmagick'
12
- rescue LoadError
13
- require 'RMagick' # capitalized on Windows
14
- end
10
+ require 'RMagick'
15
11
 
16
12
  require 'yaml'
17
13
 
18
14
  module Gruff
19
15
 
20
- VERSION = '0.0.6'
16
+ VERSION = '0.0.7'
21
17
 
22
18
  class Base
23
19
 
@@ -170,8 +166,11 @@ module Gruff
170
166
  @column_count = (data_points.length > @column_count) ? data_points.length : @column_count
171
167
 
172
168
  # Pre-normalize
173
- data_points.each do |data_point|
174
- @maximum_value = (data_point > @maximum_value) ? data_point : @maximum_value
169
+ data_points.each_with_index do |data_point, index|
170
+ next if data_point.nil?
171
+
172
+ @maximum_value = larger_than_max?(data_point, index) ? max(data_point, index) : @maximum_value
173
+ # @maximum_value = (data_point > @maximum_value) ? data_point : @maximum_value
175
174
  if @maximum_value > 0
176
175
  @has_data = true
177
176
  end
@@ -211,7 +210,11 @@ protected
211
210
  # - legend
212
211
  # - title
213
212
  def setup_drawing
214
- return unless @has_data # Maybe should be done in one of the following functions for more granularity.
213
+ # Maybe should be done in one of the following functions for more granularity.
214
+ unless @has_data
215
+ draw_no_data()
216
+ return
217
+ end
215
218
 
216
219
  normalize()
217
220
  setup_graph_measurements()
@@ -230,7 +233,11 @@ protected
230
233
  @data.each do |data_row|
231
234
  norm_data_points = Array.new
232
235
  data_row[1].each do |data_point|
233
- norm_data_points << (data_point.to_f/@maximum_value.to_f)
236
+ if data_point.nil?
237
+ norm_data_points << nil
238
+ else
239
+ norm_data_points << (data_point.to_f/@maximum_value.to_f)
240
+ end
234
241
  end
235
242
  @norm_data << [data_row[0], norm_data_points]
236
243
  end
@@ -248,7 +255,7 @@ protected
248
255
  # Draws horizontal background lines and labels
249
256
  def draw_line_markers
250
257
  return unless @show_line_markers
251
-
258
+
252
259
  # Draw horizontal line markers and annotate with numbers
253
260
  @d = @d.stroke(@marker_color)
254
261
  @d = @d.stroke_width 1
@@ -362,6 +369,19 @@ protected
362
369
  end
363
370
  end
364
371
 
372
+ def draw_no_data
373
+ @d.fill = @marker_color
374
+ @d.font = @font
375
+ @d.stroke = 'transparent'
376
+ @d.font_weight = NormalWeight
377
+ @d.pointsize = scale_fontsize(80)
378
+ @d.gravity = CenterGravity
379
+ @d = @d.annotate_scaled( @base_image,
380
+ @raw_columns, @raw_rows/2.0,
381
+ 0, 10,
382
+ 'No Data', @scale)
383
+ end
384
+
365
385
  # Use with a theme definition method to draw a gradiated (or solid color) background.
366
386
  def render_gradiated_background(top_color, bottom_color)
367
387
  Image.new(@columns, @rows,
@@ -411,6 +431,16 @@ protected
411
431
  (value > max_value) ? max_value : value
412
432
  end
413
433
 
434
+ # Overridden by subclasses such as stacked bar.
435
+ def larger_than_max?(data_point, index=0)
436
+ data_point > @maximum_value
437
+ end
438
+
439
+ def max(data_point, index)
440
+ data_point
441
+ end
442
+
443
+
414
444
  # round down to significant digits
415
445
  def significant(inc)
416
446
  factor = 1.0
@@ -440,7 +470,7 @@ protected
440
470
 
441
471
  def sums(data_set)
442
472
  total_sum = 0
443
- data_set.collect {|num| total_sum += num }
473
+ data_set.collect {|num| total_sum += num.to_f }
444
474
  total_sum
445
475
  end
446
476
 
data/lib/gruff/line.rb CHANGED
@@ -3,6 +3,12 @@ require File.dirname(__FILE__) + '/base'
3
3
 
4
4
  class Gruff::Line < Gruff::Base
5
5
 
6
+ # Draw a dashed line at the given value
7
+ attr_accessor :baseline_value
8
+
9
+ # Color of the baseline
10
+ attr_accessor :baseline_color
11
+
6
12
  #
7
13
  # Call with target pixel width of graph (800, 400, 300), and/or 'false' to omit lines (points only).
8
14
  #
@@ -19,6 +25,7 @@ class Gruff::Line < Gruff::Base
19
25
  super args.shift
20
26
  end
21
27
  @lines = args.empty? || args.shift # draw lines by default
28
+ @baseline_color = 'red'
22
29
  end
23
30
 
24
31
  def draw
@@ -31,15 +38,29 @@ class Gruff::Line < Gruff::Base
31
38
 
32
39
  @d = @d.stroke_opacity 1.0
33
40
  @d = @d.stroke_width clip_value_if_greater_than(@columns / (@norm_data.first[1].size * 4), 5.0)
34
-
41
+
42
+ if (defined?(@norm_baseline)) then
43
+ level = @graph_top + (@graph_height - @norm_baseline * @graph_height)
44
+ @d = @d.push
45
+ @d.stroke_color @baseline_color
46
+ @d.fill_opacity 0.0
47
+ @d.stroke_dasharray(10, 20)
48
+ @d.stroke_width 5
49
+ @d.line(@graph_left, level, @graph_left + @graph_width, level)
50
+ @d = @d.pop
51
+ end
52
+
35
53
  @norm_data.each do |data_row|
36
54
  prev_x = prev_y = 0.0
37
55
  @d = @d.stroke current_color
38
56
  @d = @d.fill current_color
39
57
 
40
58
  data_row[1].each_with_index do |data_point, index|
41
- # Use incremented x and scaled y
42
59
  new_x = @graph_left + (@x_increment * index)
60
+ draw_label(new_x, index)
61
+
62
+ next if data_point.nil?
63
+
43
64
  new_y = @graph_top + (@graph_height - data_point * @graph_height)
44
65
 
45
66
  if @lines and prev_x > 0 and prev_y > 0 then
@@ -47,8 +68,6 @@ class Gruff::Line < Gruff::Base
47
68
  end
48
69
  @d = @d.circle(new_x, new_y, new_x - circle_radius, new_y)
49
70
 
50
- draw_label(new_x, index)
51
-
52
71
  prev_x = new_x
53
72
  prev_y = new_y
54
73
  end
@@ -59,5 +78,8 @@ class Gruff::Line < Gruff::Base
59
78
  @d.draw(@base_image)
60
79
  end
61
80
 
62
-
81
+ def normalize
82
+ super
83
+ @norm_baseline = (@baseline_value.to_f / @maximum_value.to_f) if @baseline_value
84
+ end
63
85
  end
@@ -0,0 +1,59 @@
1
+
2
+ require File.dirname(__FILE__) + '/base'
3
+
4
+ class Gruff::StackedBar < Gruff::Base
5
+
6
+ def draw
7
+ super
8
+
9
+ return unless @has_data
10
+
11
+ # Setup spacing.
12
+ #
13
+ # Columns sit stacked.
14
+ spacing_factor = 0.9
15
+ @bar_width = @graph_width / @column_count.to_f
16
+
17
+ @d = @d.stroke_opacity 0.0
18
+
19
+ height = Array.new(@column_count, 0)
20
+
21
+ @norm_data.each_with_index do |data_row, row_index|
22
+ @d = @d.fill current_color
23
+
24
+ data_row[1].each_with_index do |data_point, point_index|
25
+ # Use incremented x and scaled y
26
+ left_x = @graph_left + (@bar_width * point_index)
27
+ left_y = @graph_top + (@graph_height -
28
+ data_point * @graph_height -
29
+ height[point_index]) + 1
30
+ right_x = left_x + @bar_width * spacing_factor
31
+ right_y = @graph_top + @graph_height - height[point_index] - 1
32
+
33
+ # update the total height of the current stacked bar
34
+ height[point_index] += (data_point * @graph_height - 2)
35
+
36
+ @d = @d.rectangle(left_x, left_y, right_x, right_y)
37
+
38
+ # Calculate center based on bar_width and current row
39
+ label_center = @graph_left + (@bar_width * point_index) + (@bar_width * spacing_factor / 2.0)
40
+ draw_label(label_center, point_index)
41
+ end
42
+
43
+ increment_color()
44
+ end
45
+
46
+ @d.draw(@base_image)
47
+ end
48
+
49
+ protected
50
+
51
+ def larger_than_max?(data_point, index=0)
52
+ max(data_point, index) > @maximum_value
53
+ end
54
+
55
+ def max(data_point, index)
56
+ @data.inject(0) {|sum, item| sum + item[1][index]}
57
+ end
58
+
59
+ end
data/test/line_test.rb CHANGED
@@ -22,29 +22,8 @@ class TestGruffLine < Test::Unit::TestCase
22
22
  end
23
23
 
24
24
  def test_line_graph_with_themes
25
- g = Gruff::Line.new
26
- g.title = "Visual Multi-Line Graph Test"
27
- g.labels = {
28
- 0 => '5/6',
29
- 2 => '5/15',
30
- 4 => '5/24',
31
- 6 => '5/30',
32
- }
33
- @datasets.each do |data|
34
- g.data(data[0], data[1])
35
- end
36
-
37
- # Default theme
38
- g.write("test/output/line_keynote.png")
39
-
40
- g.theme_37signals
41
- g.write("test/output/line_37signals.png")
42
-
43
- g.theme_rails_keynote
44
- g.write("test/output/line_rails_keynote.png")
45
-
46
- g.theme_odeo
47
- g.write("test/output/line_odeo.png")
25
+ line_graph_with_themes()
26
+ line_graph_with_themes(400)
48
27
  end
49
28
 
50
29
  def test_line_small_values
@@ -80,39 +59,15 @@ class TestGruffLine < Test::Unit::TestCase
80
59
 
81
60
  g = Gruff::Line.new
82
61
  g.title = "Very Large Values Line Graph Test"
62
+ g.baseline_value = 50_000
63
+ g.baseline_color = 'green'
83
64
  @datasets.each do |data|
84
65
  g.data(data[0], data[1])
85
66
  end
86
67
 
87
68
  g.write("test/output/line_large.png")
88
69
  end
89
-
90
- def test_resize
91
- g = Gruff::Line.new(400)
92
- g.title = "Small Size Multi-Line Graph Test"
93
- g.labels = {
94
- 0 => '5/6',
95
- 2 => '5/15',
96
- 4 => '5/24',
97
- 6 => '5/30',
98
- }
99
- @datasets.each do |data|
100
- g.data(data[0], data[1])
101
- end
102
-
103
- # Default theme
104
- g.write("test/output/line_keynote_small.png")
105
70
 
106
- g.theme_37signals
107
- g.write("test/output/line_37signals_small.png")
108
-
109
- g.theme_rails_keynote
110
- g.write("test/output/line_rails_keynote_small.png")
111
-
112
- g.theme_odeo
113
- g.write("test/output/line_odeo_small.png")
114
- end
115
-
116
71
  def test_long_title
117
72
 
118
73
  end
@@ -260,9 +215,9 @@ class TestGruffLine < Test::Unit::TestCase
260
215
  end
261
216
 
262
217
 
263
- def test_no_data_other
218
+ def test_all_zeros
264
219
  g = Gruff::Line.new(400)
265
- g.title = "No Data Other"
220
+ g.title = "All Zeros"
266
221
 
267
222
  g.data(:gus, [0,0,0,0])
268
223
 
@@ -270,6 +225,59 @@ class TestGruffLine < Test::Unit::TestCase
270
225
  g.write("test/output/line_no_data_other.png")
271
226
  end
272
227
 
228
+
229
+ def test_some_nil_points
230
+ g = Gruff::Line.new
231
+ g.title = "Some Nil Points"
232
+
233
+ @datasets = [
234
+ [:data1, [1, 2, 3, nil, 3, 5, 6]],
235
+ [:data2, [5, nil, nil, nil, nil, nil, 5]],
236
+ [:data3, [4, nil, 2, 1, 0]]
237
+ ]
238
+
239
+ @datasets.each do |data|
240
+ g.data(*data)
241
+ end
242
+
243
+ # Default theme
244
+ g.write("test/output/line_some_nil_points.png")
245
+ end
246
+
247
+ protected
248
+
249
+ def line_graph_with_themes(size=nil)
250
+ if !size.nil?
251
+ g = Gruff::Line.new(size)
252
+ else
253
+ g = Gruff::Line.new
254
+ end
255
+
256
+ g.title = "Multi-Line Graph Test #{size}"
257
+ g.labels = {
258
+ 0 => '5/6',
259
+ 2 => '5/15',
260
+ 4 => '5/24',
261
+ 6 => '5/30',
262
+ }
263
+ @datasets.each do |data|
264
+ g.data(data[0], data[1])
265
+ end
266
+
267
+ g.baseline_value = 90
268
+
269
+ # Default theme
270
+ g.write("test/output/line_theme_keynote_#{size}.png")
271
+
272
+ g.theme_37signals
273
+ g.write("test/output/line_theme_37signals_#{size}.png")
274
+
275
+ g.theme_rails_keynote
276
+ g.write("test/output/line_theme_rails_keynote_#{size}.png")
277
+
278
+ g.theme_odeo
279
+ g.write("test/output/line_theme_odeo_#{size}.png")
280
+ end
273
281
 
274
282
  end
275
283
 
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/ruby
2
+
3
+ $:.unshift(File.dirname(__FILE__) + "/../lib/")
4
+ #$:.unshift File.dirname(__FILE__) + "/fixtures/helpers"
5
+
6
+ require 'test/unit'
7
+ require 'gruff'
8
+
9
+ class TestGruffStackedBar < Test::Unit::TestCase
10
+
11
+ # TODO Delete old output files once when starting tests
12
+
13
+ def setup
14
+ @datasets = [
15
+ [:Jimmy, [25, 36, 86, 39]],
16
+ [:Charles, [80, 54, 67, 54]],
17
+ [:Julie, [22, 29, 35, 38]],
18
+ #[:Jane, [95, 95, 95, 90, 85, 80, 88, 100]],
19
+ #[:Philip, [90, 34, 23, 12, 78, 89, 98, 88]],
20
+ #["Arthur", [5, 10, 13, 11, 6, 16, 22, 32]],
21
+ ]
22
+ end
23
+
24
+ def test_bar_graph
25
+ g = Gruff::StackedBar.new
26
+ g.title = "Visual Stacked Bar Graph Test"
27
+ g.labels = {
28
+ 0 => '5/6',
29
+ 1 => '5/15',
30
+ 2 => '5/24',
31
+ 3 => '5/30',
32
+ }
33
+ @datasets.each do |data|
34
+ g.data(data[0], data[1])
35
+ end
36
+
37
+ g.write("test/output/stacked_bar_keynote.png")
38
+
39
+ g.theme_rails_keynote
40
+ g.write("test/output/stacked_bar_rails_keynote.png")
41
+
42
+ g.theme_odeo
43
+ g.write("test/output/stacked_bar_odeo.png")
44
+ end
45
+
46
+
47
+ def test_bar_graph_small
48
+ g = Gruff::StackedBar.new(400)
49
+ g.title = "Visual Stacked Bar Graph Test"
50
+ g.labels = {
51
+ 0 => '5/6',
52
+ 1 => '5/15',
53
+ 2 => '5/24',
54
+ 3 => '5/30',
55
+ }
56
+ @datasets.each do |data|
57
+ g.data(data[0], data[1])
58
+ end
59
+
60
+ g.write("test/output/stacked_bar_keynote_small.png")
61
+ end
62
+
63
+ def test_bar_image_bg
64
+ g = Gruff::StackedBar.new
65
+ g.title = "Stacked Bar Graph With Image Background"
66
+ g.labels = {
67
+ 0 => '5/6',
68
+ 1 => '5/15',
69
+ 2 => '5/24',
70
+ 3 => '5/30',
71
+ }
72
+ @datasets.each do |data|
73
+ g.data(data[0], data[1])
74
+ end
75
+
76
+ g.theme_image_based
77
+ g.write("test/output/stacked_bar_image.png")
78
+
79
+ g = Gruff::StackedBar.new(400)
80
+ g.title = "Stacked Bar Graph With Image Background Small"
81
+ g.labels = {
82
+ 0 => '5/6',
83
+ 1 => '5/15',
84
+ 2 => '5/24',
85
+ 3 => '5/30',
86
+ }
87
+ @datasets.each do |data|
88
+ g.data(data[0], data[1])
89
+ end
90
+
91
+ g.theme_image_based
92
+ g.write("test/output/stacked_bar_image_small.png")
93
+
94
+ end
95
+
96
+
97
+ end
98
+
99
+ class Gruff::Base
100
+ def theme_image_based
101
+ reset_themes()
102
+ # Colors
103
+ @green = '#00ff00'
104
+ @grey = '#333333'
105
+ @orange = '#ff5d00'
106
+ @red = '#f61100'
107
+ @white = 'white'
108
+ @light_grey = '#999999'
109
+ @black = 'black'
110
+ @colors = [@green, @grey, @orange, @red, @white, @light_grey, @black]
111
+
112
+ @marker_color = 'white'
113
+
114
+ @base_image = render_image_background('assets/bubble.png')
115
+ end
116
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: gruff
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.0.6
7
- date: 2005-11-22 00:00:00 -08:00
6
+ version: 0.0.7
7
+ date: 2005-12-04 00:00:00 -08:00
8
8
  summary: Beautiful graphs for one or multiple datasets.
9
9
  require_paths:
10
10
  - lib
@@ -40,13 +40,16 @@ files:
40
40
  - lib/gruff/base.rb
41
41
  - lib/gruff/line.rb
42
42
  - lib/gruff/pie.rb
43
+ - lib/gruff/stacked_bar.rb
43
44
  - assets/bubble.png
44
45
  - assets/plastik
46
+ - assets/plastik-yellow.png
45
47
  - test/area_test.rb
46
48
  - test/bar_test.rb
47
49
  - test/line_test.rb
48
50
  - test/output
49
51
  - test/pie_test.rb
52
+ - test/stacked_bar_test.rb
50
53
  test_files: []
51
54
  rdoc_options: []
52
55
  extra_rdoc_files: []