Module: DataLayerProcessorSimpleSmoother

Included in:
DataLayerProcessor
Defined in:
lib/technical_graph/data_layer_processor_simple_smoother.rb

Constant Summary collapse

SIMPLE_SMOOTHER_STRATEGIES =

Smoothing

{
  :rectangular => 'generate_vector_rectangular',
  :gauss => 'generate_vector_gauss'
}
DEFAULT_SIMPLE_SMOOTHER_STRATEGY =
:gauss
MIN_SIMPLE_SMOOTHER_LEVEL =
1
MAX_SIMPLE_SMOOTHER_LEVEL =
200
PROCESS_WITH_PARAMETER_DISTANCE =

use ‘x’ axis for processing also

false
DEFAULT_GAUSS_COEFF =

default Gauss coefficient

0.2

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#gauss_coeffObject

Returns the value of attribute gauss_coeff.



31
32
33
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 31

def gauss_coeff
  @gauss_coeff
end

#simple_smootherObject (readonly)

Returns the value of attribute simple_smoother.



30
31
32
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 30

def simple_smoother
  @simple_smoother
end

#simple_smoother_levelObject

Returns the value of attribute simple_smoother_level.



38
39
40
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 38

def simple_smoother_level
  @simple_smoother_level
end

#simple_smoother_strategyObject

Returns the value of attribute simple_smoother_strategy.



46
47
48
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 46

def simple_smoother_strategy
  @simple_smoother_strategy
end

#simple_smoother_xObject

smooth using X distance



49
50
51
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 49

def simple_smoother_x
  @simple_smoother_x
end

#vectorObject (readonly)

Returns the value of attribute vector.



30
31
32
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 30

def vector
  @vector
end

Instance Method Details

#generate_vectorObject

This vector will be used to process values (Y’es) Use proper simple_smoother_strategy



53
54
55
56
57
58
59
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 53

def generate_vector
  method = SIMPLE_SMOOTHER_STRATEGIES[@simple_smoother_strategy]
  if method.nil?
    method = SIMPLE_SMOOTHER_STRATEGIES[DEFAULT_SIMPLE_SMOOTHER_STRATEGY]
  end
  return self.send(method)
end

#generate_vector_gaussObject

This vector will be used to process values (Y’es), linear algorithm



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 167

def generate_vector_gauss
  # http://www.techotopia.com/index.php/Ruby_Math_Functions_and_Methods#Ruby_Math_Constants
  # http://pl.wikipedia.org/wiki/Okno_czasowe

  # calculation
  count = (simple_smoother_level.to_f / 2.0).floor + 1

  v = Array.new
  # calculated
  (1..count).each do |i|
    v << Math::E ** ((-0.5) * (i*gauss_coeff) ** 2)
  end

  @vector = make_mirror(v, simple_smoother_level)

  normalize_vector

  return @vector
end

#generate_vector_rectangularObject

This vector will be used to process values (Y’es), linear algorithm



157
158
159
160
161
162
163
164
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 157

def generate_vector_rectangular
  @vector = Array.new
  # calculated
  (1..simple_smoother_level).each do |i|
    @vector << 1.0 / simple_smoother_level.to_f
  end
  return @vector
end

#make_mirror(input, size) ⇒ Object

Make mirror array size = 7 => [ i, i, i, i, i, i, i ] size = 8 => [ i, i, i, i, i, i, i, i ]



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 208

def make_mirror(input, size)
  a = Array.new(size, 0.1)
  if size.even?
    # two 'first' in central
    c_left = size/2 - 1
    c_right = size/2

    a[c_left] = input[0]
    a[c_right] = input[0]
  else
    # there is one 'first'
    c_left = (size/2.0).floor
    c_right = (size/2.0).floor

    a[c_left] = input[0]
    # a[c_right] = input[0]
  end

  # the rest
  i = 0
  while c_left > 0
    i += 1
    c_left -= 1
    c_right += 1

    a[c_left] = input[i]
    a[c_right] = input[i]
  end

  return a
end

#normalize_vectorObject

Multiply vector to have sum eq. 1.0



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 188

def normalize_vector
  s = 0.0
  @vector.each do |v|
    s += v
  end

  new_vector = Array.new

  @vector.each do |v|
    new_vector << v / s
  end

  @vector = new_vector

  return @vector
end

#process_part(old_data, position, y_based = true) ⇒ Object

Process part (size depends on simple_smoother_level)



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 104

def process_part(old_data, position, y_based = true)
  # neutral data, used where position is near edge to calculate new value
  neutral_data = DataPoint.xy(old_data[position].x, old_data[position].y)
  part_array = Array.new(simple_smoother_level, neutral_data)

  # add data from old_data to part_array
  offset = (simple_smoother_level/2.0).floor
  # copying data
  (0...simple_smoother_level).each do |l|
    copy_pos = position + l - offset
    # if copy_pos is inside data
    if copy_pos >= 0 and old_data.size > copy_pos
      part_array[l] = old_data[copy_pos]
    end
  end
  # here we should have part_array and vector
  # and now do some magic :]


  if y_based
    return process_part_only_y(part_array)
  else
    return process_part_only_x(part_array, neutral_data)
  end
end

#process_part_only_x(part_array, neutral_data) ⇒ Object

Process part (size depends on simple_smoother_level), Y and X data



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 140

def process_part_only_x(part_array, neutral_data)
  weights = Array.new
  w_sum = 0.0
  (0...simple_smoother_level).each do |l|
    p = part_array[l]
    x_distance = p.x_distance(neutral_data)
    w = (Math::E ** (-1.0 * 0.2 * x_distance)) + 1.0
    w_sum += w
    weights << w
  end

  w_prod = 0.0
  part_array.each_index { |i| w_prod += part_array[i].y * weights[i].to_f }
  return w_prod.to_f / w_sum.to_f
end

#process_part_only_y(part_array, neutral_data = nil) ⇒ Object

Process part (size depends on simple_smoother_level), only Y data



131
132
133
134
135
136
137
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 131

def process_part_only_y(part_array, neutral_data = nil)
  y_sum = 0.0
  (0...simple_smoother_level).each do |l|
    y_sum += part_array[l].y * vector[l]
  end
  return y_sum
end

#simple_smoother_initialize(options) ⇒ Object



20
21
22
23
24
25
26
27
28
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 20

def simple_smoother_initialize(options)
  @simple_smoother = options[:simple_smoother] == true
  @simple_smoother_strategy = options[:simple_smoother_strategy] || DEFAULT_SIMPLE_SMOOTHER_STRATEGY
  @simple_smoother_level = options[:simple_smoother_level] || MIN_SIMPLE_SMOOTHER_LEVEL
  @simple_smoother_x = options[:simple_smoother_x] == true

  @vector = Array.new
  @gauss_coeff = DEFAULT_GAUSS_COEFF
end

#simple_smoother_processObject

Smooth values



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/technical_graph/data_layer_processor_simple_smoother.rb', line 62

def simple_smoother_process
  # not turned on
  return if simple_smoother == false

  # vector used for smoothing
  generate_vector

  t = Time.now
  old_data = @data
  new_data = Array.new

  # pre-processing, distance
  if simple_smoother_x == true
    logger.debug "X axis distance smoothing enabled"
    t = Time.now

    (0...old_data.size).each do |i|
      new_data << DataPoint.xy(old_data[i].x, process_part(old_data, i, false))
    end

    old_data = new_data
    new_data = Array.new

    logger.debug "X axis distance smoothing completed"
    logger.debug " TIME COST #{Time.now - t}"
  end

  logger.debug "Y axis distance smoothing"
  t = Time.now

  (0...old_data.size).each do |i|
    new_data << DataPoint.xy(old_data[i].x, process_part(old_data, i))
  end

  logger.debug "Y axis Smoothing completed, simple_smoother_level #{simple_smoother_level}, data size #{old_data.size}"
  logger.debug " TIME COST #{Time.now - t}"

  @data = new_data
  return new_data
end