analytica 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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