lib/sparklines.rb in sparklines-0.4.1 vs lib/sparklines.rb in sparklines-0.4.2
- old
+ new
@@ -72,11 +72,11 @@
Licensed under the MIT license.
=end
class Sparklines
- VERSION = '0.4.1'
+ VERSION = '0.4.2'
@@label_margin = 5.0
@@pointsize = 10.0
class << self
@@ -99,14 +99,16 @@
:share_color => 'red',
:remain_color => 'lightgrey',
:min_color => 'blue',
:max_color => 'green',
:last_color => 'red',
+ :std_dev_color => '#efefef',
:has_min => false,
:has_max => false,
:has_last => false,
+ :has_std_dev => false,
:label => nil
}
# HACK for HashWithIndifferentAccess
@@ -142,41 +144,41 @@
end
##
# Creates a continuous area sparkline. Relevant options.
#
- # :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
- #
- # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
- #
- # :upper - An integer that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50.
- #
- # :has_min - Determines whether a dot will be drawn at the lowest value or not. Defaults to false.
- #
- # :has_max - Determines whether a dot will be drawn at the highest value or not. Defaults to false.
- #
- # :has_last - Determines whether a dot will be drawn at the last value or not. Defaults to false.
- #
- # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue.
- #
- # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
- #
- # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
- #
- # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
- #
- # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
+ # :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
+ #
+ # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
+ #
+ # :upper - An integer that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50.
+ #
+ # :has_min - Determines whether a dot will be drawn at the lowest value or not. Defaults to false.
+ #
+ # :has_max - Determines whether a dot will be drawn at the highest value or not. Defaults to false.
+ #
+ # :has_last - Determines whether a dot will be drawn at the last value or not. Defaults to false.
+ #
+ # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue.
+ #
+ # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
+ #
+ # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
+ #
+ # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
+ #
+ # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
def area
- step = @options[:step].to_i
- height = @options[:height].to_i
+ step = @options[:step].to_f
+ height = @options[:height].to_f
background_color = @options[:background_color]
create_canvas((@norm_data.size - 1) * step + 4, height, background_color)
- upper = @options[:upper].to_i
+ upper = @options[:upper].to_f
has_min = @options[:has_min]
has_max = @options[:has_max]
has_last = @options[:has_last]
@@ -201,19 +203,19 @@
@draw.fill(above_color)
@draw.define_clip_path('top') do
@draw.rectangle(0,0,(@norm_data.size - 1) * step + 4,(height - 3 - upper/(101.0/(height-4))))
end
@draw.clip_path('top')
- @draw.polygon *coords.flatten
+ @draw.polygon(*coords.flatten)
# Block off the top half of the image and draw the sparkline
@draw.fill(below_color)
@draw.define_clip_path('bottom') do
@draw.rectangle(0,(height - 3 - upper/(101.0/(height-4))),(@norm_data.size - 1) * step + 4,height)
end
@draw.clip_path('bottom')
- @draw.polygon *coords.flatten
+ @draw.polygon(*coords.flatten)
# The sparkline looks kinda nasty if either the above_color or below_color gets the center line
@draw.fill('black')
@draw.line(0,(height - 3 - upper/(101.0/(height-4))),(@norm_data.size - 1) * step + 4,(height - 3 - upper/(101.0/(height-4))))
@@ -235,17 +237,17 @@
##
# A bar graph.
def bar
- step = @options[:step].to_i
+ step = @options[:step].to_f
height = @options[:height].to_f
background_color = @options[:background_color]
create_canvas(@norm_data.length * step + 2, height, background_color)
- upper = @options[:upper].to_i
+ upper = @options[:upper].to_f
below_color = @options[:below_color]
above_color = @options[:above_color]
i = 1
@norm_data.each_with_index do |r, index|
@@ -263,36 +265,41 @@
##
# Creates a discretized sparkline
#
- # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
+ # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
#
- # :upper - An integer that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50.
+ # :upper - An integer that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50.
#
- # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
+ # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
#
- # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
+ # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
def discrete
- height = @options[:height].to_i
- upper = @options[:upper].to_i
+ height = @options[:height].to_f
+ upper = @options[:upper].to_f
background_color = @options[:background_color]
- step = @options[:step].to_i
+ step = @options[:step].to_f
+
+ width = @norm_data.size * step - 1
- create_canvas(@norm_data.size * step - 1, height, background_color)
+ create_canvas(width, height, background_color)
below_color = @options[:below_color]
above_color = @options[:above_color]
+ std_dev_color = @options[:std_dev_color]
+ drawstddevbox(width,height,std_dev_color) if @options[:has_std_dev] == true
+
i = 0
@norm_data.each do |r|
color = (r >= upper) ? above_color : below_color
@draw.stroke(color)
- @draw.line(i, (@canvas.rows - r/(101.0/(height-4))-4).to_i,
- i, (@canvas.rows - r/(101.0/(height-4))).to_i)
+ @draw.line(i, (@canvas.rows - r/(101.0/(height-4))-4).to_f,
+ i, (@canvas.rows - r/(101.0/(height-4))).to_f)
i += step
end
@draw.draw(@canvas)
@canvas.to_blob
@@ -300,18 +307,18 @@
##
# Creates a pie-chart sparkline
#
- # :diameter - An integer that determines what the size of the sparkline will be. Defaults to 20
+ # :diameter - An integer that determines what the size of the sparkline will be. Defaults to 20
#
- # :share_color - A string or color code representing the color to draw the share of the pie represented by percent. Defaults to red.
+ # :share_color - A string or color code representing the color to draw the share of the pie represented by percent. Defaults to red.
#
- # :remain_color - A string or color code representing the color to draw the pie not taken by the share color. Defaults to lightgrey.
+ # :remain_color - A string or color code representing the color to draw the pie not taken by the share color. Defaults to lightgrey.
def pie
- diameter = @options[:diameter].to_i
+ diameter = @options[:diameter].to_f
background_color = @options[:background_color]
create_canvas(diameter, diameter, background_color)
share_color = @options[:share_color]
@@ -368,41 +375,51 @@
##
# Creates a smooth sparkline.
#
- # :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
+ # :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
#
- # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
+ # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
#
- # :has_min - Determines whether a dot will be drawn at the lowest value or not. Defaults to false.
+ # :has_min - Determines whether a dot will be drawn at the lowest value or not. Defaults to false.
#
- # :has_max - Determines whether a dot will be drawn at the highest value or not. Defaults to false.
+ # :has_max - Determines whether a dot will be drawn at the highest value or not. Defaults to false.
#
- # :has_last - Determines whether a dot will be drawn at the last value or not. Defaults to false.
+ # :has_last - Determines whether a dot will be drawn at the last value or not. Defaults to false.
#
- # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue.
+ # :has_std_dev - Determines whether there will be a standard deviation bar behind the smooth graph or not. Defaults to false.
#
- # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
+ # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue.
#
- # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
+ # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
+ #
+ # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
+ #
+ # :std_dev_color - A string or color code representing the color that the standard deviation bar behind the smooth graph will be displayed as. Defaults to #efefef
def smooth
- step = @options[:step].to_i
- height = @options[:height].to_i
+ step = @options[:step].to_f
+ height = @options[:height].to_f
background_color = @options[:background_color]
- create_canvas((@norm_data.size - 1) * step + 4, height, background_color)
+ width = (@norm_data.size - 1) * step + 4
+
+ create_canvas(width, height, background_color)
min_color = @options[:min_color]
max_color = @options[:max_color]
last_color = @options[:last_color]
has_min = @options[:has_min]
has_max = @options[:has_max]
has_last = @options[:has_last]
line_color = @options[:line_color]
+ has_std_dev = @options[:has_std_dev]
+ std_dev_color = @options[:std_dev_color]
+
+ drawstddevbox(width,height,std_dev_color) if has_std_dev == true
@draw.stroke(line_color)
coords = []
i=0
@norm_data.each do |r|
@@ -432,20 +449,20 @@
#
# * results - an array of integer values between -2 and 2. -2 is exceptional
# down, 1 is regular down, 0 is no value, 1 is up, and 2 is exceptional up.
# * options - a hash that takes parameters
#
- # :height - height of the sparkline
+ # :height - height of the sparkline
#
- # :whisker_color - the color of regular whiskers; defaults to black
+ # :whisker_color - the color of regular whiskers; defaults to black
#
- # :exception_color - the color of exceptional whiskers; defaults to red
+ # :exception_color - the color of exceptional whiskers; defaults to red
def whisker
- # step = @options[:step].to_i
- height = @options[:height].to_i
+ # step = @options[:step].to_f
+ height = @options[:height].to_f
background_color = @options[:background_color]
create_canvas((@data.size - 1) * 2, height, background_color)
whisker_color = @options[:whisker_color] || 'black'
@@ -503,11 +520,11 @@
@norm_data = @data.map { |value| value = (value.to_f / @maximum_value) * 100.0 }
end
end
##
- # * :arr - an array of points (represented as two element arrays)
+ # :arr - an array of points (represented as two element arrays)
def open_ended_polyline(arr)
0.upto(arr.length - 2) { |i|
@draw.line(arr[i][0], arr[i][1], arr[i+1][0], arr[i+1][1])
}
@@ -519,10 +536,11 @@
# TODO Refactor into smaller methods
def create_canvas(w, h, bkg_col)
@draw = Magick::Draw.new
@draw.pointsize = @@pointsize # TODO Use height
+ @draw.pointsize = @options[:font_size] if @options.has_key?(:font_size)
@canvas = Magick::Image.new(w , h) { self.background_color = bkg_col }
# Make room for label and last value
unless @options[:label].nil?
@options[:has_last] = true
@@ -542,10 +560,11 @@
vera_font_path = File.expand_path('Vera.ttf', ENV['MAGICK_FONT_PATH'])
@font = File.exists?(vera_font_path) ? vera_font_path : nil
else
@font = nil
end
+ @font = @options[:font] if @options.has_key?(:font)
@draw.fill = 'black'
@draw.font = @font if @font
@draw.gravity = Magick::WestGravity
@draw.annotate( @canvas,
@@ -569,14 +588,56 @@
@draw.stroke 'transparent'
@draw.fill(color)
@draw.rectangle(pt[0]-offset, pt[1]-offset, pt[0]+offset, pt[1]+offset)
end
+ ##
+ # Utility to draw the standard deviation box
+ #
+ def drawstddevbox(width,height,color)
+ mid=@norm_data.inject(0) {|sum,v| sum+=v}/@norm_data.size
+ std_dev = standard_deviation(@norm_data)/100*height
+ @draw.stroke 'transparent'
+ @draw.fill(color)
+ @draw.rectangle(0, mid-std_dev, width, mid+std_dev)
+ end
+
def calculate_width(text)
@draw.get_type_metrics(@canvas, text.to_s).width
end
def calculate_caps_height
@draw.get_type_metrics(@canvas, 'X').height
end
+ ##
+ # Calculation helper for standard deviation.
+ #
+ # Thanks to Warren Seen
+ # http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/
+ def variance(population)
+ n = 0
+ mean = 0.0
+ s = 0.0
+ population.each { |x|
+ n = n + 1
+ delta = x - mean
+ mean = mean + (delta / n)
+ s = s + delta * (x - mean)
+ }
+ # if you want to calculate std deviation
+ # of a sample change this to "s / (n-1)"
+ return s / n
+ end
+
+ ##
+ # Calculate the standard deviation of a population
+ #
+ # accepts: an array, the population
+ # returns: the standard deviation
+ def standard_deviation(population)
+ Math.sqrt(variance(population))
+ end
+
+
end
+