module DataLayerProcessorSimpleSmoother

encoding: utf-8

Constants

DEFAULT_GAUSS_COEFF

default Gauss coefficient

DEFAULT_SIMPLE_SMOOTHER_STRATEGY
MAX_SIMPLE_SMOOTHER_LEVEL
MIN_SIMPLE_SMOOTHER_LEVEL
PROCESS_WITH_PARAMETER_DISTANCE

use 'x' axis for processing also

SIMPLE_SMOOTHER_STRATEGIES

Smoothing

Attributes

gauss_coeff[RW]
simple_smoother[R]
simple_smoother_level[R]
simple_smoother_strategy[R]
simple_smoother_x[RW]

smooth using X distance

vector[R]

Public Instance Methods

generate_vector() click to toggle source

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

# 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_gauss() click to toggle source

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

# 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_rectangular() click to toggle source

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

# 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) click to toggle source

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

# 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_vector() click to toggle source

Multiply vector to have sum eq. 1.0

# 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) click to toggle source

Process part (size depends on simple_smoother_level)

# 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) click to toggle source

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

# 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) click to toggle source

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

# 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) click to toggle source
# 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_level=(l) click to toggle source

Simple_smoother_level of approximation

# File lib/technical_graph/data_layer_processor_simple_smoother.rb, line 34
def simple_smoother_level=(l)
  @simple_smoother_level = l.to_i if l.to_i >= MIN_SIMPLE_SMOOTHER_LEVEL and l.to_i < MAX_SIMPLE_SMOOTHER_LEVEL
end
simple_smoother_process() click to toggle source

Smooth values

# 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
simple_smoother_strategy=(s) click to toggle source

Choose other simple_smoother_strategy from SIMPLE_SMOOTHER_STRATEGIES

# File lib/technical_graph/data_layer_processor_simple_smoother.rb, line 41
def simple_smoother_strategy=(s)
  method = SIMPLE_SMOOTHER_STRATEGIES[s]
  @simple_smoother_strategy = s unless method.nil?
end