class Digiproc::DigitalSignal

Class for performing actions on Digital Signals easily

Attributes

data[RW]

Public Class Methods

new(data: ) click to toggle source

Initialize with `data`

# File lib/signals/digital_signal.rb, line 40
def initialize(data: )
    raise ArgumentError.new("Data must be an Array, not a #{data.class}") if not data.is_a? Array
    @data = data
    initialize_modules(Digiproc::FourierTransformable => {time_data: data})
end
new_from_eqn(eqn: , size: ) click to toggle source

Construct an instance from a Proc (or a Lambda) and a size

ds = Digiproc::DigitalSignal.new_from_eqn(eqn: ->(t){ Math.sin(t) }, size: 100)
# File lib/signals/digital_signal.rb, line 10
def self.new_from_eqn(eqn: , size: )
    rng = (0...size)
    self.new(data: rng.map{ |n| eqn.call(n) })
end
new_from_equations(eqns: , ranges: ) click to toggle source

Make a digital signal which is defined by one equation in one range, and another eqn in another range

eqn1 = ->(t){ (1 - Math::E ** (-0.08*t)) } 
eqn2 = ->(t){ Math::E ** (-0.002*(t - 100)) }
ds = Digiproc::DigitalSignal.new_from_equations(eqns: [eqn1, eqn2], ranges: [0...100, 100...1000])
# File lib/signals/digital_signal.rb, line 20
def self.new_from_equations(eqns: , ranges: )
    data = []
    eqns.each_with_index do |eqn, i|
        ranges[i].each do |n|
            data[n] = eqn.call(n)
        end
    end
    data.map!{ |val| val.nil? ? 0 : val }
    self.new(data: data)
end

Public Instance Methods

*(ds) click to toggle source

Allows multiplication of two digital signal objects Performs element by element multiplicaiton of the data vectors

# File lib/signals/digital_signal.rb, line 81
def *(ds)
    raise ArgumentError.new("Object must have a data property") unless ds.respond_to? :data
    raise ArgumentError.new("Object must have a data array") unless ds.data.respond_to? :times
    self.data.length < ds.data.length ? self.class.new(data:self.data.times(ds.data.take(self.data.length))) : self.class.new(data: ds.data.times(self.data.take(ds.data.length))) 
    # self.data.times ds.data
end
cross_spectral_density(signal) click to toggle source

Returns the cross_spectral_density of the digital signal with an incoming signal (accepts an array of numeric data) Returns a Digiproc::FFT object

# File lib/signals/digital_signal.rb, line 164
def cross_spectral_density(signal)
    ft = Digiproc::FFT.new(time_data: self.xcorr(signal))
    ft.calculate
    ft
end
csd(signal) click to toggle source

Alias for cross_spectral_density

# File lib/signals/digital_signal.rb, line 172
def csd(signal)
    self.cross_spectral_density(signal)
end
ds_acorr() click to toggle source

Alias to ds_auto_correlation

# File lib/signals/digital_signal.rb, line 144
def ds_acorr
    ds_auto_correlation
end
ds_auto_correlation() click to toggle source

Performs an autocorrelation of the `data` array and retursn a Digiproc::DigitalSignal whose data is the result of the autocorrelation

# File lib/signals/digital_signal.rb, line 138
def ds_auto_correlation
    Digiproc::DigitalSignal.new(data: self.auto_correlation)
end
ds_conv(signal) click to toggle source

Alias to ds_convolve

# File lib/signals/digital_signal.rb, line 120
def ds_conv(signal)
    Digiproc::DigitalSignal.new(data: self.conv(signal))
end
ds_convolve(signal) click to toggle source

Convolves data with incoming signal, returns a new Digiproc::DigitalSignal whose data is the result of the convolution

# File lib/signals/digital_signal.rb, line 114
def ds_convolve(signal)
    Digiproc::DigitalSignal.new(data: self.conv(signal))
end
ds_cross_correlation(signal) click to toggle source

Performs cross correlation with an incoming signal, returns a Digiproc::DigitalSignal whose data is the result of the cross correlation

# File lib/signals/digital_signal.rb, line 126
def ds_cross_correlation(signal)
    Digiproc::DigitalSignal.new(data: self.cross_correlation(signal))
end
ds_xcorr(sig) click to toggle source

Alias for ds_cross_correlation

# File lib/signals/digital_signal.rb, line 132
def ds_xcorr(sig)
    ds_cross_correlation(sig)
end
i(*n) click to toggle source

Get data values from @data by index

ds = Digiproc::DigitalSignal.new_from_eqn(eqn: ->(t){ Math.sin(t) }, size: 100)
vals = ds.i(10..12) # => [-0.5440211108893699, -0.9999902065507035, -0.5365729180004349]
# File lib/signals/digital_signal.rb, line 92
def i(*n)
    indices = n.map{ |input| input.respond_to?(:to_a) ? input.to_a : input}
    indices.flatten!
    indices.map!{ |val| self.value_at val }
    return indices.length == 1 ? indices.first : indices
end
new_from_spectra(fft) click to toggle source

Make a new digital signal from fft data

# File lib/signals/digital_signal.rb, line 34
def new_from_spectra(fft)
    self.new(data: Digiproc::Functions.ifft(fft))
end
power_spectral_density() click to toggle source

Returns the Power Spectral Density (PSD) of the signal by multiplying the signal's FFT by the conjugate of the FFT (ie squaring the FFT) The result is in the frequency spectrum (as a Digiproc::FFT object)

# File lib/signals/digital_signal.rb, line 151
def power_spectral_density
    self.fft * self.fft.conjugate
end
process() { |data)| ... } click to toggle source

Helper method to allow user to process a ds data using a block

ds = Digiproc::DigitalSignal.new_from_eqn(eqn: ->(t){ Math.sin(t) }, size: 100)
ds.process { |el| el * 10 } # Change signal gain from 1 to 10.

Does not change @data, just returns processed array

# File lib/signals/digital_signal.rb, line 51
def process 
    processed_data = []
    for i in 0...data.length do
        processed_data << (yield data[i])
    end
    processed_data
end
process!() { |data)| ... } click to toggle source

Same as `#process` except @data is replaced by the output

# File lib/signals/digital_signal.rb, line 61
def process!
    processed_data = []
    for i in 0...data.length do
        processed_data << (yield data[i])
    end
    self.data = processed_data
end
process_in_place!() { |data| ... } click to toggle source

Updates data while processing, allowing recursive processing (ie using prev outputs to create new ones)

# File lib/signals/digital_signal.rb, line 71
def process_in_place!
    for i in 0...data.length do 
        self.data[i] = yield data[i]
    end
    self.data
end
psd() click to toggle source

Alias to power_spectral_density

# File lib/signals/digital_signal.rb, line 157
def psd
    self.power_spectral_density
end
to_a() click to toggle source

Returns data as an array

# File lib/signals/digital_signal.rb, line 178
def to_a
    self.data
end
value_at(n) click to toggle source

Get the value at a specific data index. If index falls outside of the `data` array, return 0 This is useful when simulating a signal multiplied by a unit step which is zero outside the bounds defined in the data array

# File lib/signals/digital_signal.rb, line 102
def value_at(n)
    data[n].nil? ? 0 : data[n]
end
values_between(start,stop) click to toggle source

Get values in the data array from a start index to a start index (inclusive). Does not turn data outside array into a 0 value

# File lib/signals/digital_signal.rb, line 108
def values_between(start,stop)
    data[start, stop - start + 1]
end