module Digiproc::DataProperties

Module which can perform basic operations on 1D data arrays This module extends itself so all methods can be called via:

Digiproc::DataProperties.method_i_want_to_call

Public Instance Methods

all_maxima(data) click to toggle source
all_maxima(data [Array]) => returns Array(OpenStruct<#index, #value>)

returns all maximum in an array of `OpenStruct`s with index and value, ie:

all_maxima([1,2,3,4,5,4,3,2,6,7,8,7,6,5])   # [#<OpenStruct index=4, value=5>, #<OpenStruct index=10, value=8>]
# File lib/concerns/data_properties.rb, line 13
def all_maxima(data)
    raise ArgumentError.new("Data must be an array") if not data.is_a? Array
    slope = Slope::Positive
    max = []
    data.each_with_index do |n, i|
        old_slope = slope
        if i <= data.length - 2
            new_slope = find_slope(data[i], data[i+1])
            slope = new_slope.is?(:zero) ? old_slope : new_slope
            max << OpenStruct.new(index: i, value: n) if old_slope.is? :positive and slope.is? :negative
        else
            max << OpenStruct.new(index: i, value: n) if slope.is? :positive
        end
    end
    max
end
find_slope(a,b) click to toggle source

find_slope(a: Int or Double, b: Int or Double) returns Slope::Positive, Slope::Negative, or Slope::Zero Note: Slope::Positive.is? :positive returns true, Slope::Negative.is? :negative returns true, etc.

# File lib/concerns/data_properties.rb, line 80
def find_slope(a,b)
    slope = nil
    if b - a > 0
        slope = Slope::Positive
    elsif b - a < 0
        slope = Slope::Negative
    else
        slope = Slope::Zero
    end
    slope
end
local_maxima(data, num=1) click to toggle source

local_maxima(data [Array], num=1 [Integer]) => returns Array(OpenStruct(index, value)) calculates all maxima and orders them by how much proportionally they are to any directly adjacent maxima. It then takes `num` answer and returns an array of `OpenStruct`s with index and value This is particularly useful to use when looking for local maxima in a FFT dB or magnitude plot.

arr = [50,45,40,30,35,30,29,28,29,20,15,10,19,9,8,7,9,8,7,6,5,9,6,5,4,9,6,3,2,7,5,4,3,2,1,9,1,2,3,4]
Digiproc::DataProperties.local_maxima(arr, 3)  #=> [#<OpenStruct index=35, value=9>, #<OpenStruct index=0, value=50>, #<OpenStruct index=12, value=19>]
# File lib/concerns/data_properties.rb, line 45
def local_maxima(data, num=1)
    all_maxima = all_maxima(data)
    all_maxima.sort do |a, b|
        a_upper = all_maxima.find{ |maxima| maxima.index > a.index }
        a_lower = all_maxima.reverse.find{ |maxima| maxima.index < a.index }
        a_adjacent = 0
        if a_upper && a_lower
            a_adjacent = ((a.value.to_f / a_upper.value) + (a.value.to_f / a_lower.value))  / 2.0
        else
            a_adjacent = !!a_upper ? (a.value.to_f / a_upper.value) : (a.value.to_f / a_lower.value)
        end
        b_upper = all_maxima.find{ |maxima| maxima.index > b.index }
        b_lower = all_maxima.reverse.find{ |maxima| maxima.index < b.index }
        b_adjacent = 0
        if b_upper && b_lower
            b_adjacent = ((b.value.to_f / b_upper.value) +  (b.value.to_f / b_lower.value))  / 2.0
        else
            b_adjacent = !!b_upper ? (b.value.to_f / b_upper.value) : (b.value.to_f / b_lower.value)
        end
        b_adjacent <=> a_adjacent
    end
    .take(num)
end
maxima(data, num = 1) click to toggle source

maxima(data [Array], num = 1 [Integer]) returns `num` number of largest maxima from the data array returned in all_maxima

arr = [1,2,3,4,5,4,3,2,6,7,8,7,6,5]
Digiproc::DataProperties.maxima(arr, 1) # => [#<OpenStruct index=10, value=8>]
# File lib/concerns/data_properties.rb, line 34
def maxima(data, num = 1)
    all_maxima(data).sort{ |a, b| b.value <=> a.value }.take num
end
slope(a,b, range=1) click to toggle source

slope(a: Numeric, b: Numeric, range=1: Numeric ) => float returns the slope of these two y values, given a change in x values by `range` which defualts to 1. Returns a float

Digiproc::DataProperties.slope(0.5, 1.2, 0.5) #=> 1.4
# File lib/concerns/data_properties.rb, line 73
def slope(a,b, range=1)
    return (b - a) / range.to_f
end