Module: Digiproc::DataProperties

Extended by:
DataProperties
Included in:
DataProperties, Functions
Defined in:
lib/concerns/data_properties.rb

Overview

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

Defined Under Namespace

Classes: Slope

Instance Method Summary collapse

Instance Method Details

#all_maxima(data) ⇒ Object

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() # [#<OpenStruct index=4, value=5>, #<OpenStruct index=10, value=8>]

Raises:

  • (ArgumentError)


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 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) ⇒ Object

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.



80
81
82
83
84
85
86
87
88
89
90
# 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) ⇒ Object

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>]


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# 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) ⇒ Object

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>]



34
35
36
# 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) ⇒ Object

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



73
74
75
# File 'lib/concerns/data_properties.rb', line 73

def slope(a,b, range=1)
    return (b - a) / range.to_f
end