analytica 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 0.0.7 / 2010-08-09
2
+ * 3 enhancements
3
+
4
+ * Cleaned up structure of analytica package
5
+ * Analytica::DataSet now has a default constructor (empty DataSet) + type-safety on 'concat' and '+'
6
+ * Implemented moving_average, lma, sma and ema + approprate sub-computations
7
+
1
8
  === 0.0.5 / 2010-08-03
2
9
 
3
10
  * 3 enhancements
data/Manifest.txt CHANGED
@@ -4,6 +4,6 @@ README.txt
4
4
  Rakefile
5
5
  bin/analytica
6
6
  lib/analytica.rb
7
- lib/analytica_comp.rb
8
- lib/analytica_viz.rb
7
+ lib/computation.rb
8
+ lib/visualization.rb
9
9
  test/test_analytica.rb
data/lib/analytica.rb CHANGED
@@ -1,16 +1,16 @@
1
1
  require 'typestrict'
2
2
 
3
- require File.join(File.dirname(__FILE__), 'analytica_comp')
4
- require File.join(File.dirname(__FILE__), 'analytica_viz')
3
+ require File.join(File.dirname(__FILE__), 'computation')
4
+ require File.join(File.dirname(__FILE__), 'visualization')
5
5
 
6
6
  module Analytica
7
- VERSION = '0.0.6'
7
+ VERSION = '0.0.7'
8
8
 
9
9
  include Strict
10
10
 
11
11
  class DataSet < Array
12
- include Computation
13
- include Visualization
12
+ include Analytica::Computation
13
+ include Analytica::Visualization
14
14
 
15
15
  def initialize(datapoints=[])
16
16
  enforce!(:numeric_array, datapoints)
@@ -22,5 +22,15 @@ module Analytica
22
22
  enforce!(:numeric, object)
23
23
  super object
24
24
  end
25
+
26
+ def concat(other)
27
+ enforce!(:numeric_array, other)
28
+ super other
29
+ end
30
+
31
+ def +(other)
32
+ enforce!(:numeric_array, other)
33
+ super other
34
+ end
25
35
  end
26
36
  end
@@ -0,0 +1,209 @@
1
+ require 'typestrict'
2
+
3
+ module Analytica
4
+ module Computation
5
+ include Strict
6
+
7
+ class InvalidInputException < Exception
8
+ def initialize(comp, size, params, constraints)
9
+ enforce!([:average_filter,
10
+ :moving_average], comp)
11
+ enforce_primitive!(Hash, params)
12
+ enforce!(:string_array, constraints)
13
+
14
+ @msg = "Unable to calculate #{comp.inspect} on DataSet size #{size} with input #{params.inspect}"
15
+ @msg += "\nConstraints:\n"
16
+ constraints.each do |c|
17
+ @msg += c+"\n"
18
+ end
19
+ end
20
+
21
+ def inspect
22
+ @msg
23
+ end
24
+ end
25
+
26
+ def sum
27
+ sum = inject { |sum, x| sum + x }
28
+ sum ? sum : 0
29
+ end
30
+
31
+ def mean
32
+ sum.to_f / size
33
+ end
34
+
35
+ def linear_mean(params)
36
+ enforce_map!({
37
+ :bias => [:last, :first],
38
+ :samples => :natural_number}, params)
39
+
40
+ data = self
41
+ data.reverse! if params[:bias] == :last
42
+
43
+ params[:samples] = [params[:samples], data.size].min
44
+
45
+ n = params[:samples] + 1
46
+ numerator = 0.0
47
+ denominator = 0.0
48
+
49
+ data.each do |sample|
50
+ n -= 1
51
+ n = n > 0 ? n : 0
52
+
53
+ numerator += n*sample
54
+ denominator += n
55
+ end
56
+ numerator / denominator
57
+ end
58
+
59
+ def exponential_mean(params)
60
+ enforce_map!({
61
+ :bias => [:last, :first],
62
+ :alpha => :numeric,
63
+ :samples => :integer}, params)
64
+
65
+ data = self
66
+ data.reverse! if params[:bias] == :last
67
+
68
+ params[:samples] = [params[:samples], data.size].min
69
+
70
+ ema = 0
71
+ counter = 0
72
+ alpha = params[:alpha]
73
+
74
+ data.each do |sample|
75
+
76
+ if counter > params[:samples]
77
+ break
78
+ end
79
+
80
+ if counter == 0
81
+ ema += sample
82
+ else
83
+ ema += sample * (1-alpha)**counter
84
+ end
85
+
86
+ counter += 1
87
+ end
88
+ alpha*ema
89
+ end
90
+
91
+
92
+ def average_filter(params)
93
+ enforce_map!({
94
+ :decay => [:simple, :linear, :exponential],
95
+ :offset => :natural_number, # offset from latest data point
96
+ :samples => :natural_number}, params)
97
+
98
+ if !(params[:offset] <= size)
99
+ c = InvalidInputException.new(:simple_average,
100
+ size,
101
+ params,
102
+ [":offset <= :size"])
103
+ raise c, c.inspect, caller
104
+ end
105
+
106
+ if !(params[:offset] >= params[:samples])
107
+ c = InvalidInputException.new(:simple_average,
108
+ size,
109
+ params,
110
+ [":offset >= :samples"])
111
+ raise c, c.inspect, caller
112
+ end
113
+
114
+ i = size - params[:offset]
115
+ j = i + params[:samples]-1
116
+
117
+ d = DataSet.new(self[i..j])
118
+
119
+ case params[:decay]
120
+ when :simple
121
+ d.mean
122
+ when :linear
123
+ d.linear_mean(:bias => :last, :samples => d.size)
124
+ when :exponential
125
+ enforce_exists!(:alpha, params)
126
+ enforce!(:numeric, params[:alpha])
127
+ d.exponential_mean(:bias => :first, :samples => d.size, :alpha => params[:alpha])
128
+ end
129
+ end
130
+
131
+ alias_method(:avg, :average_filter)
132
+
133
+ def moving_average(params)
134
+ enforce_map!({
135
+ :decay => [:simple, :linear, :exponential],
136
+ :samples => :natural_number}, params)
137
+
138
+ if !(size >= (2*params[:samples]-1))
139
+ c = InvalidInputException.new(:moving_average,
140
+ size,
141
+ params,
142
+ ["size >= (2*:samples-1)"])
143
+ raise c, c.inspect, caller
144
+ end
145
+
146
+ d = DataSet.new
147
+ (1..params[:samples]).each do |offset|
148
+ d << average_filter(:decay => params[:decay], :alpha => params[:alpha], :offset => offset+params[:samples]-1, :samples => params[:samples])
149
+ end
150
+ d.reverse
151
+ end
152
+
153
+ def simple_moving_average(params)
154
+ enforce_map!({
155
+ :samples => :natural_number}, params)
156
+ moving_average(:decay => :simple, :samples => params[:samples])
157
+ end
158
+
159
+ alias_method :sma, :simple_moving_average
160
+
161
+ def linear_moving_average(params)
162
+ enforce_map!({
163
+ :samples => :natural_number}, params)
164
+ moving_average(:decay => :linear, :samples => params[:samples])
165
+ end
166
+
167
+ alias_method :lma, :linear_moving_average
168
+
169
+ def exponential_moving_average(params)
170
+ enforce_map!({
171
+ :samples => :integer,
172
+ :alpha=> :float}, params)
173
+
174
+ moving_average(:decay => :exponential, :samples => params[:samples], :alpha => params[:alpha])
175
+ end
176
+
177
+ alias_method :ema, :exponential_moving_average
178
+
179
+ def piecewise_derivative(n=1)
180
+ enforce!(:natural_number, n)
181
+
182
+ d = self
183
+ n.times do
184
+ d = d.inject([]) do |result, item|
185
+ if result.size == 0
186
+ result << item
187
+ else
188
+ d_y = (item - result.last).to_f
189
+ d_x = 1.0 #account for d_x eventually
190
+ deriv = d_y/d_x
191
+ result.pop
192
+ result << deriv
193
+ result << item unless (result.size) == (d.size-1)
194
+ result
195
+ end
196
+ end
197
+ end
198
+ DataSet.new(d)
199
+ end
200
+
201
+ alias_method :dydx, :piecewise_derivative
202
+
203
+ def savitzky_golay(n=1)
204
+ enforce!(:natural_number, n)
205
+
206
+ raise "savitzy_golay filter not yet implemented!"
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,68 @@
1
+ require 'typestrict'
2
+ require 'gchart'
3
+
4
+ class GChart::Base
5
+ def to_html
6
+ "<img src=\"#{self.to_url}\" />"
7
+ end
8
+ end
9
+
10
+ module Analytica
11
+ module Visualization
12
+ include Strict
13
+
14
+ def set_labels(labels)
15
+ enforce!(:string_array, labels)
16
+
17
+ @labels = labels
18
+ end
19
+
20
+ def datamax
21
+ (max > 0) ? max : 1
22
+ end
23
+
24
+ def to_linegraph(params)
25
+ enforce_map!({
26
+ :width => :natural_number,
27
+ :height => :natural_number,
28
+ :background_color => :hex_color,
29
+ :color => :hex_color}, params)
30
+
31
+ GChart.line do |g|
32
+ g.data = self
33
+ g.extras = {
34
+ 'chm' => 'N*cUSD0*,000000,0,-1,11',
35
+ 'chbh' => '18,38',
36
+ 'chds' => "0,#{datamax}"
37
+ }
38
+ g.size = "#{(params[:width]).to_i}x#{(params[:height]).to_i}"
39
+ g.entire_background = params[:background_color].to_s
40
+ g.colors = params[:color].to_s
41
+ g.axis(:bottom) {|a| a.labels = @labels}
42
+ end
43
+ end
44
+
45
+ def to_bargraph(params)
46
+ enforce_map!({
47
+ :width => :natural_number,
48
+ :height => :natural_number,
49
+ :orientation => [:vertical, :horizontal],
50
+ :background_color => :hex_color,
51
+ :color => :hex_color}, params)
52
+
53
+ GChart.bar do |g|
54
+ g.data = self
55
+ g.extras = {
56
+ 'chm' => 'N*cUSD0*,000000,0,-1,11',
57
+ 'chbh' => '45,30',
58
+ 'chds' => "0,#{datamax}"
59
+ }
60
+ g.size = "#{(params[:width]).to_i}x#{(params[:height]).to_i}"
61
+ g.entire_background = params[:background_color].to_s
62
+ g.colors = params[:color].to_s
63
+ g.orientation = params[:orientation]
64
+ g.axis(:bottom) {|a| a.labels = @labels}
65
+ end
66
+ end
67
+ end
68
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: analytica
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ - 7
10
+ version: 0.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Raeez Lorgat
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-07 00:00:00 -04:00
18
+ date: 2010-08-09 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -81,8 +81,8 @@ files:
81
81
  - Rakefile
82
82
  - bin/analytica
83
83
  - lib/analytica.rb
84
- - lib/analytica_comp.rb
85
- - lib/analytica_viz.rb
84
+ - lib/computation.rb
85
+ - lib/visualization.rb
86
86
  - test/test_analytica.rb
87
87
  has_rdoc: true
88
88
  homepage: http://www.raeez.com/anlaytica
@@ -1,95 +0,0 @@
1
- require 'typestrict'
2
-
3
- module Computation
4
- include Strict
5
-
6
- def sum
7
- sum = inject { |sum, x| sum + x }
8
- sum ? sum : 0
9
- end
10
-
11
- def mean
12
- sum.to_f / size
13
- end
14
-
15
- def linear_moving_average(params)
16
- enforce_map!({
17
- :bias => [:last, :first],
18
- :samples => :integer}, params)
19
-
20
- data = []
21
- case params[:bias]
22
- when :last
23
- data = self.reverse
24
- when :first
25
- data = self
26
- else
27
- raise "Bias not legally set!"
28
- end
29
-
30
- params[:samples] = [params[:samples], data.size]
31
-
32
- n = params[:samples] + 1
33
- numerator = 0.0
34
- denominator = 0.0
35
-
36
- data.each do |sample|
37
- n -= 1
38
- n = n > 0 ? n : 0
39
-
40
- numerator += n*sample
41
- denominator += n
42
- end
43
- numerator / denominator
44
- end
45
-
46
- alias_method :lma, :linear_moving_average
47
-
48
- def exponential_moving_average(params)
49
- enforce_map!({
50
- :decay => [:exponential, :linear],
51
- :decay_bias => [:latest, :oldest],
52
- :decay_coefficent => :float}, params)
53
-
54
- raise "ema not yet implemented!"
55
-
56
- if params[:decay_bias] == :latest
57
- data = self
58
- else
59
- data = self.reverse
60
- end
61
- 0.0
62
- end
63
-
64
- alias_method :ema, :exponential_moving_average
65
-
66
- def piecewise_derivative(n=1)
67
- enforce!(:natural_number, n)
68
-
69
- d = self
70
- n.times do
71
- d = d.inject([]) do |result, item|
72
- if result.size == 0
73
- result << item
74
- else
75
- d_y = (item - result.last).to_f
76
- d_x = 1.0 #account for d_x eventually
77
- deriv = d_y/d_x
78
- result.pop
79
- result << deriv
80
- result << item unless (result.size) == (d.size-1)
81
- result
82
- end
83
- end
84
- end
85
- DataSet.new(d)
86
- end
87
-
88
- alias_method :dydx, :piecewise_derivative
89
-
90
- def savitzky_golay(n=1)
91
- enforce!(:natural_number, n)
92
-
93
- raise "savitzy_golay filter not yet implemented!"
94
- end
95
- end
data/lib/analytica_viz.rb DELETED
@@ -1,67 +0,0 @@
1
- require 'typestrict'
2
-
3
- require 'gchart'
4
-
5
- class GChart::Base
6
- def to_html
7
- "<img src=\"#{self.to_url}\" />"
8
- end
9
- end
10
-
11
- module Visualization
12
- include Strict
13
-
14
- def set_labels(labels)
15
- enforce!(:string_array, labels)
16
-
17
- @labels = labels
18
- end
19
-
20
- def datamax
21
- (max > 0) ? max : 1
22
- end
23
-
24
- def to_linegraph(params)
25
- enforce_map!({
26
- :width => :natural_number,
27
- :height => :natural_number,
28
- :background_color => :hex_color,
29
- :color => :hex_color}, params)
30
-
31
- GChart.line do |g|
32
- g.data = self
33
- g.extras = {
34
- 'chm' => 'N*cUSD0*,000000,0,-1,11',
35
- 'chbh' => '18,38',
36
- 'chds' => "0,#{datamax}"
37
- }
38
- g.size = "#{(params[:width]).to_i}x#{(params[:height]).to_i}"
39
- g.entire_background = params[:background_color].to_s
40
- g.colors = params[:color].to_s
41
- g.axis(:bottom) {|a| a.labels = @labels}
42
- end
43
- end
44
-
45
- def to_bargraph(params)
46
- enforce_map!({
47
- :width => :natural_number,
48
- :height => :natural_number,
49
- :orientation => [:vertical, :horizontal],
50
- :background_color => :hex_color,
51
- :color => :hex_color}, params)
52
-
53
- GChart.bar do |g|
54
- g.data = self
55
- g.extras = {
56
- 'chm' => 'N*cUSD0*,000000,0,-1,11',
57
- 'chbh' => '45,30',
58
- 'chds' => "0,#{datamax}"
59
- }
60
- g.size = "#{(params[:width]).to_i}x#{(params[:height]).to_i}"
61
- g.entire_background = params[:background_color].to_s
62
- g.colors = params[:color].to_s
63
- g.orientation = params[:orientation]
64
- g.axis(:bottom) {|a| a.labels = @labels}
65
- end
66
- end
67
- end