Class: Digiproc::DigitalSignal
- Inherits:
-
Object
- Object
- Digiproc::DigitalSignal
- Includes:
- Convolvable::InstanceMethods, FourierTransformable
- Defined in:
- lib/signals/digital_signal.rb
Overview
Class for performing actions on Digital Signals easily
Instance Attribute Summary collapse
-
#data ⇒ Object
Returns the value of attribute data.
Attributes included from FourierTransformable
Class Method Summary collapse
-
.new_from_eqn(eqn:, size:) ⇒ Object
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).
-
.new_from_equations(eqns:, ranges:) ⇒ Object
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]).
Instance Method Summary collapse
-
#*(ds) ⇒ Object
Allows multiplication of two digital signal objects Performs element by element multiplicaiton of the data vectors.
-
#cross_spectral_density(signal) ⇒ Object
Returns the cross_spectral_density of the digital signal with an incoming signal (accepts an array of numeric data) Returns a Digiproc::FFT object.
-
#csd(signal) ⇒ Object
Alias for #cross_spectral_density.
-
#ds_acorr ⇒ Object
Alias to #ds_auto_correlation.
-
#ds_auto_correlation ⇒ Object
Performs an autocorrelation of the ‘data` array and retursn a Digiproc::DigitalSignal whose data is the result of the autocorrelation.
-
#ds_conv(signal) ⇒ Object
Alias to ds_convolve.
-
#ds_convolve(signal) ⇒ Object
Convolves data with incoming signal, returns a new Digiproc::DigitalSignal whose data is the result of the convolution.
-
#ds_cross_correlation(signal) ⇒ Object
Performs cross correlation with an incoming signal, returns a Digiproc::DigitalSignal whose data is the result of the cross correlation.
-
#ds_xcorr(sig) ⇒ Object
Alias for #ds_cross_correlation.
-
#i(*n) ⇒ Object
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].
-
#initialize(data:) ⇒ DigitalSignal
constructor
Initialize with ‘data`.
-
#new_from_spectra(fft) ⇒ Object
Make a new digital signal from fft data.
-
#power_spectral_density ⇒ Object
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).
-
#process ⇒ Object
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.
-
#process! ⇒ Object
Same as ‘#process` except @data is replaced by the output.
-
#process_in_place! ⇒ Object
Updates data while processing, allowing recursive processing (ie using prev outputs to create new ones).
-
#psd ⇒ Object
Alias to #power_spectral_density.
-
#to_a ⇒ Object
Returns data as an array.
-
#value_at(n) ⇒ Object
Get the value at a specific data index.
-
#values_between(start, stop) ⇒ Object
Get values in the data array from a start index to a start index (inclusive).
Methods included from Convolvable::InstanceMethods
#acorr, #auto_correlation, #conv, #convolution_strategy, #convolve, #cross_correlation, included, #xcorr
Methods included from FourierTransformable
#fft_angle, #fft_data, #fft_db, #fft_imaginary, #fft_magnitude, #fft_real, included
Constructor Details
#initialize(data:) ⇒ DigitalSignal
Initialize with ‘data`
40 41 42 43 44 |
# 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 |
Instance Attribute Details
#data ⇒ Object
Returns the value of attribute data.
4 5 6 |
# File 'lib/signals/digital_signal.rb', line 4 def data @data end |
Class Method Details
.new_from_eqn(eqn:, size:) ⇒ Object
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)
10 11 12 13 |
# 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:) ⇒ Object
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])
20 21 22 23 24 25 26 27 28 29 |
# 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 |
Instance Method Details
#*(ds) ⇒ Object
Allows multiplication of two digital signal objects Performs element by element multiplicaiton of the data vectors
81 82 83 84 85 86 |
# 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) ⇒ Object
Returns the cross_spectral_density of the digital signal with an incoming signal (accepts an array of numeric data) Returns a Digiproc::FFT object
164 165 166 167 168 |
# 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) ⇒ Object
Alias for #cross_spectral_density
172 173 174 |
# File 'lib/signals/digital_signal.rb', line 172 def csd(signal) self.cross_spectral_density(signal) end |
#ds_acorr ⇒ Object
Alias to #ds_auto_correlation
144 145 146 |
# File 'lib/signals/digital_signal.rb', line 144 def ds_acorr ds_auto_correlation end |
#ds_auto_correlation ⇒ Object
Performs an autocorrelation of the ‘data` array and retursn a Digiproc::DigitalSignal whose data is the result of the autocorrelation
138 139 140 |
# File 'lib/signals/digital_signal.rb', line 138 def ds_auto_correlation Digiproc::DigitalSignal.new(data: self.auto_correlation) end |
#ds_conv(signal) ⇒ Object
Alias to ds_convolve
120 121 122 |
# File 'lib/signals/digital_signal.rb', line 120 def ds_conv(signal) Digiproc::DigitalSignal.new(data: self.conv(signal)) end |
#ds_convolve(signal) ⇒ Object
Convolves data with incoming signal, returns a new Digiproc::DigitalSignal whose data is the result of the convolution
114 115 116 |
# File 'lib/signals/digital_signal.rb', line 114 def ds_convolve(signal) Digiproc::DigitalSignal.new(data: self.conv(signal)) end |
#ds_cross_correlation(signal) ⇒ Object
Performs cross correlation with an incoming signal, returns a Digiproc::DigitalSignal whose data is the result of the cross correlation
126 127 128 |
# 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) ⇒ Object
Alias for #ds_cross_correlation
132 133 134 |
# File 'lib/signals/digital_signal.rb', line 132 def ds_xcorr(sig) ds_cross_correlation(sig) end |
#i(*n) ⇒ Object
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]
92 93 94 95 96 97 |
# 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) ⇒ Object
Make a new digital signal from fft data
34 35 36 |
# File 'lib/signals/digital_signal.rb', line 34 def new_from_spectra(fft) self.new(data: Digiproc::Functions.ifft(fft)) end |
#power_spectral_density ⇒ Object
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)
151 152 153 |
# File 'lib/signals/digital_signal.rb', line 151 def power_spectral_density self.fft * self.fft.conjugate end |
#process ⇒ Object
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
51 52 53 54 55 56 57 |
# 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! ⇒ Object
Same as ‘#process` except @data is replaced by the output
61 62 63 64 65 66 67 |
# 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! ⇒ Object
Updates data while processing, allowing recursive processing (ie using prev outputs to create new ones)
71 72 73 74 75 76 |
# 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 ⇒ Object
Alias to #power_spectral_density
157 158 159 |
# File 'lib/signals/digital_signal.rb', line 157 def psd self.power_spectral_density end |
#to_a ⇒ Object
Returns data as an array
178 179 180 |
# File 'lib/signals/digital_signal.rb', line 178 def to_a self.data end |
#value_at(n) ⇒ Object
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
102 103 104 |
# File 'lib/signals/digital_signal.rb', line 102 def value_at(n) data[n].nil? ? 0 : data[n] end |
#values_between(start, stop) ⇒ Object
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
108 109 110 |
# File 'lib/signals/digital_signal.rb', line 108 def values_between(start,stop) data[start, stop - start + 1] end |