digiproc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +48 -0
- data/LICENSE.txt +21 -0
- data/README.md +78 -0
- data/Rakefile +37 -0
- data/TODO.md +50 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/environment.rb +118 -0
- data/console_tests.rb +44 -0
- data/digiproc.gemspec +49 -0
- data/examples/analog_signals/analog_to_digital.rb +31 -0
- data/examples/analog_signals/companded-signals.png +0 -0
- data/examples/analog_signals/companding.rb +68 -0
- data/examples/analog_signals/fft-plot.png +0 -0
- data/examples/analog_signals/plot_Digiproc::FFT.png +0 -0
- data/examples/analog_signals/plot_Dsp::FFT.png +0 -0
- data/examples/analog_signals/quantization-outputs.png +0 -0
- data/examples/analog_signals/quantize_compand.rb +69 -0
- data/examples/binomial_distribution/bit_error.rb +14 -0
- data/examples/binomial_distribution/dice.rb +35 -0
- data/examples/digital_signals/_coded_frequency_signal,_ts_=_1_s.png +0 -0
- data/examples/digital_signals/_coded_frequency_signal,_ts_=_2_s.png +0 -0
- data/examples/digital_signals/coded_power_spectral_density,__ts_=_1_s.png +0 -0
- data/examples/digital_signals/coded_power_spectral_density,__ts_=_2_s.png +0 -0
- data/examples/digital_signals/coded_time_signal,_ts_=_1_s.png +0 -0
- data/examples/digital_signals/coded_time_signal,_ts_=_2_s.png +0 -0
- data/examples/digital_signals/freq_sig_from_eqn,_ts_=_1_s.png +0 -0
- data/examples/digital_signals/freq_sig_from_eqn,_ts_=_2_s.png +0 -0
- data/examples/digital_signals/frequency_signal,_ts_=_1_s.png +0 -0
- data/examples/digital_signals/frequency_signal,_ts_=_2_s.png +0 -0
- data/examples/digital_signals/modulate_square_pulses.rb +9 -0
- data/examples/digital_signals/modulated_sq._pulses.png +0 -0
- data/examples/digital_signals/modulated_sq._pulses_alt.png +0 -0
- data/examples/digital_signals/power_spectral_density,__ts_=_1_s.png +0 -0
- data/examples/digital_signals/power_spectral_density,__ts_=_2_s.png +0 -0
- data/examples/digital_signals/square_signals.rb +90 -0
- data/examples/digital_signals/time_signal,_ts_=_1_s.png +0 -0
- data/examples/digital_signals/time_signal,_ts_=_2_s.png +0 -0
- data/examples/encoding/gray_code.rb +22 -0
- data/examples/encoding/psk.rb +91 -0
- data/examples/encoding/system_2_phase.png +0 -0
- data/examples/encoding/system_2_xmit_signal.png +0 -0
- data/examples/encoding/system_3_phase.png +0 -0
- data/examples/encoding/system_3_xmit_signal.png +0 -0
- data/examples/encoding/system_4_xmit_signal.png +0 -0
- data/examples/encoding/xor-dpsk-phase-signal-(sys1).png +0 -0
- data/examples/encoding/xor-dpsk-xmit-signal-(sys-1).png +0 -0
- data/examples/factories/Quickplot Graph.png +0 -0
- data/examples/factories/bandpass.rb +6 -0
- data/examples/fft/plot_Dsp::FFT.png +0 -0
- data/examples/fft/recieved_data_(time_domain).png +0 -0
- data/examples/fft/simple_fft_example.rb +47 -0
- data/examples/fft/unprocessed_fft.png +0 -0
- data/examples/filters/bandpass_filter.png +0 -0
- data/examples/filters/filter_a_signal.rb +38 -0
- data/examples/filters/white_noise_db_out_of_bp_filter.png +0 -0
- data/examples/filters/white_noise_mag_out_of_bp_filter.png +0 -0
- data/examples/filters/white_noise_spectra.png +0 -0
- data/examples/functions/compute_probability.rb +29 -0
- data/examples/functions/gram_schmidt.rb +10 -0
- data/examples/functions/minimize_energy.rb +29 -0
- data/examples/functions/orthoganalize.rb +18 -0
- data/examples/functions/simple_functions.rb +81 -0
- data/examples/linear_algebra/diverging_sys.rb +13 -0
- data/examples/linear_algebra/iterative_sys_of_eqns_methods.rb +27 -0
- data/examples/modulation_schemes/dpsk_2.png +0 -0
- data/examples/modulation_schemes/dpsk_256.png +0 -0
- data/examples/modulation_schemes/dpsk_freq_domain.rb +119 -0
- data/examples/modulation_schemes/psk.rb +36 -0
- data/examples/modulation_schemes/psk_2.png +0 -0
- data/examples/modulation_schemes/psk_256.png +0 -0
- data/examples/modulation_schemes/psksystem_1_xmit_signal.png +0 -0
- data/examples/modulation_schemes/psksystem_2_xmit_signal.png +0 -0
- data/examples/modulation_schemes/psksystem_3_xmit_signal.png +0 -0
- data/examples/modulation_schemes/system_1_xmit_signal.png +0 -0
- data/examples/modulation_schemes/system_2_xmit_signal.png +0 -0
- data/examples/modulation_schemes/system_3_xmit_signal.png +0 -0
- data/examples/quickplot/PlottableClass_plot.png +0 -0
- data/examples/quickplot/decorators.rb +13 -0
- data/examples/quickplot/direct_gruff.png +0 -0
- data/examples/quickplot/plot_PlottableClass.png +0 -0
- data/examples/quickplot/quickplot_vs_others.rb +85 -0
- data/examples/quickplot/random_data_quickplot,_dark.png +0 -0
- data/examples/quickplot/random_data_quickplot.png +0 -0
- data/examples/realized_gaussian/norm_dist_plot.png +0 -0
- data/examples/realized_gaussian/norm_dist_spectrum.png +0 -0
- data/examples/realized_gaussian/realized_gaussian_example.rb +23 -0
- data/lib/concerns/convolvable.rb +144 -0
- data/lib/concerns/data_properties.rb +223 -0
- data/lib/concerns/fourier_transformable.rb +178 -0
- data/lib/concerns/initializable.rb +43 -0
- data/lib/concerns/multipliable.rb +22 -0
- data/lib/concerns/os.rb +36 -0
- data/lib/concerns/plottable.rb +248 -0
- data/lib/concerns/requires_data.rb +8 -0
- data/lib/digiproc/version.rb +8 -0
- data/lib/digiproc.rb +2 -0
- data/lib/extensions/array_extension.rb +23 -0
- data/lib/extensions/core_extensions.rb +117 -0
- data/lib/factories/factories.rb +3 -0
- data/lib/factories/filter_factory.rb +83 -0
- data/lib/factories/window_factory.rb +22 -0
- data/lib/fft.rb +255 -0
- data/lib/filters/bandpass_filter.rb +43 -0
- data/lib/filters/bandstop_filter.rb +44 -0
- data/lib/filters/digital_filter.rb +59 -0
- data/lib/filters/highpass_filter.rb +27 -0
- data/lib/filters/lowpass_filter.rb +27 -0
- data/lib/functions.rb +221 -0
- data/lib/probability/binomial_distribution.rb +84 -0
- data/lib/probability/bit_generator.rb +94 -0
- data/lib/probability/gaussian_distribution.rb +29 -0
- data/lib/probability/probability.rb +234 -0
- data/lib/probability/theoretical_gaussian_distribution.rb +59 -0
- data/lib/quick_plot.rb +96 -0
- data/lib/rbplot.rb +219 -0
- data/lib/signals/analog_signal.rb +143 -0
- data/lib/signals/digital_signal.rb +181 -0
- data/lib/strategies/code/differential_encoding_strategy.rb +69 -0
- data/lib/strategies/code/gray_code.rb +75 -0
- data/lib/strategies/code/xor_differential_encoding_strategy.rb +100 -0
- data/lib/strategies/code/xor_differential_encoding_zero_angle_strategy.rb +103 -0
- data/lib/strategies/companding/custom_companding_strategy.rb +29 -0
- data/lib/strategies/convolution/bf_conv.rb +57 -0
- data/lib/strategies/fft/brute_force_dft_strategy.rb +31 -0
- data/lib/strategies/fft/inverse_fft_conjugate_strategy.rb +44 -0
- data/lib/strategies/fft/radix2_strategy.rb +84 -0
- data/lib/strategies/gaussian/gaussian_generator.rb +49 -0
- data/lib/strategies/linear_algebra/gauss_seidel_strategy.rb +90 -0
- data/lib/strategies/linear_algebra/jacobi_strategy.rb +81 -0
- data/lib/strategies/linear_algebra/sor2_strategy.rb +98 -0
- data/lib/strategies/linear_algebra/sor_strategy.rb +108 -0
- data/lib/strategies/modulation/phase_shift_keying_strategy.rb +96 -0
- data/lib/strategies/orthogonalize/gram_schmidt.rb +50 -0
- data/lib/strategies/strategies.rb +3 -0
- data/lib/strategies/window/blackman_window.rb +32 -0
- data/lib/strategies/window/hamming_window.rb +31 -0
- data/lib/strategies/window/hanning_window.rb +31 -0
- data/lib/strategies/window/kaiser_window.rb +27 -0
- data/lib/strategies/window/rectangular_window.rb +22 -0
- data/lib/strategies/window/window.rb +42 -0
- data/lib/systems/custom_system.rb +13 -0
- data/lib/systems/hilbert_transform.rb +6 -0
- data/lib/systems/matched_filter.rb +21 -0
- data/lib/systems/raised_cosine_filter.rb +11 -0
- data/lib/systems/system.rb +19 -0
- data/lib/systems/systems.rb +3 -0
- data/playground.rb +323 -0
- data/plots/_coded_frequency_signal,_ts_=_1_s.png +0 -0
- data/plots/_coded_frequency_signal,_ts_=_2_s.png +0 -0
- data/plots/coded_freq_sig_from_eqn,_ts_=_1_s.png +0 -0
- data/plots/coded_freq_sig_from_eqn,_ts_=_2_s.png +0 -0
- data/plots/coded_power_spectral_density,__ts_=_1_s.png +0 -0
- data/plots/coded_power_spectral_density,__ts_=_2_s.png +0 -0
- data/plots/coded_time_signal,_ts_=_1_s.png +0 -0
- data/plots/coded_time_signal,_ts_=_2_s.png +0 -0
- data/plots/dpsk_2.png +0 -0
- data/plots/freq_sig_from_eqn,_ts_=_1_s.png +0 -0
- data/plots/freq_sig_from_eqn,_ts_=_2_s.png +0 -0
- data/plots/frequency_signal,_ts_=_1_s.png +0 -0
- data/plots/frequency_signal,_ts_=_2_s.png +0 -0
- data/plots/power_spectral_density,__ts_=_1_s.png +0 -0
- data/plots/power_spectral_density,__ts_=_2_s.png +0 -0
- data/plots/psk_2.png +0 -0
- data/plots/time_signal,_ts_=_1_s.png +0 -0
- data/plots/time_signal,_ts_=_2_s.png +0 -0
- data/test-title-dark.png +0 -0
- data/test-title.png +0 -0
- metadata +322 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
points1 = [[2,1,3],[1,2,4],[-3,-2,-4],[1,-2,4]]
|
|
2
|
+
points2 = [[0,1,0],[1,3,3],[-2,-5,-4],[-1,-2,-4]]
|
|
3
|
+
|
|
4
|
+
# => #translate_center_to_origin can take arguments of individual arrays (of the same length), an array of the points, or an array of a hash with
|
|
5
|
+
# the points as the keys and the probability of the points as the value. If no probabilities are given, each point is assumed to be
|
|
6
|
+
# equiprobable. The points are then centered around the origin as to reduce the total energy of the points.
|
|
7
|
+
|
|
8
|
+
min_energy_1 = Digiproc::Functions.translate_center_to_origin(points1)
|
|
9
|
+
min_energy_2 = Digiproc::Functions.translate_center_to_origin(points2)
|
|
10
|
+
|
|
11
|
+
puts "Translated version of #{points1}: \n\t\n#{min_energy_1}"
|
|
12
|
+
puts "\n\n"
|
|
13
|
+
puts "Translated version of #{points2}: \n\t\n#{min_energy_2}"
|
|
14
|
+
puts "\n\n"
|
|
15
|
+
probabilities = [1.0/3, 1.0 / 6, 1.0/6, 1.0/3]
|
|
16
|
+
points_probs_1 = {}
|
|
17
|
+
points_probs_2 = {}
|
|
18
|
+
|
|
19
|
+
for i in 0...points1.length do
|
|
20
|
+
points_probs_1[points1[i]] = probabilities[i]
|
|
21
|
+
points_probs_2[points2[i]] = probabilities[i]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
min_energy_3 = Digiproc::Functions.translate_center_to_origin(points_probs_1)
|
|
25
|
+
min_energy_4 = Digiproc::Functions.translate_center_to_origin(points_probs_2)
|
|
26
|
+
|
|
27
|
+
puts "Translated version of #{points_probs_1}: \n\t\n#{min_energy_3}"
|
|
28
|
+
puts "\n\n"
|
|
29
|
+
puts "Translated version of #{points_probs_2}: \n\t\n#{min_energy_4}"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
|
|
2
|
+
gs = Digiproc::Strategies::GramSchmidtOrthonormalize
|
|
3
|
+
eqn1 = ->(t){Math::E ** (-t)}
|
|
4
|
+
eqn2 = ->(t){Math::E ** (-2*t)}
|
|
5
|
+
eqn3 = ->(t){Math::E ** (-3*t)}
|
|
6
|
+
|
|
7
|
+
set1 = Digiproc::AnalogSignal.new(eqn: eqn1, size: 10000, sample_rate:0.1).digitize
|
|
8
|
+
set2 = Digiproc::AnalogSignal.new(eqn: eqn2, size: 10000, sample_rate:0.1).digitize
|
|
9
|
+
set3 = Digiproc::AnalogSignal.new(eqn: eqn3, size: 10000, sample_rate:0.1).digitize
|
|
10
|
+
|
|
11
|
+
out1, out2, out3 = gs.new([set1,set2,set3]).output
|
|
12
|
+
|
|
13
|
+
puts "out1 dot out2 = #{out1.dot out2}"
|
|
14
|
+
puts "out1 dot out3 = #{out1.dot out3}"
|
|
15
|
+
puts "out2 dot out3 = #{out2.dot out3}"
|
|
16
|
+
|
|
17
|
+
puts "All three are orthogonal becacuse their dot products are 0"
|
|
18
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# ***** Simple functions examples from Digiproc::Functions and Digiproc::Probability *****
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#Gaussian random number generator
|
|
5
|
+
pfuncs = Digiproc::Probability
|
|
6
|
+
nums = []
|
|
7
|
+
10.times do
|
|
8
|
+
nums << pfuncs.nrand
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
puts "Numbers from gaussian distribution:"
|
|
12
|
+
puts nums.to_s
|
|
13
|
+
puts
|
|
14
|
+
|
|
15
|
+
# Pearson's Correlation Coefficient from Digiproc::Probability
|
|
16
|
+
dist1 = Digiproc::Probability::RealizedGaussianDistribution.new(mean: 0, stddev: 10, size: 100).data
|
|
17
|
+
dist2 = Digiproc::Probability::RealizedGaussianDistribution.new(mean: 0, stddev: 10, size: 100).data
|
|
18
|
+
corr_coeff = pfuncs.correlation_coefficient(dist1, dist2)
|
|
19
|
+
corr_coeff_2 = pfuncs.correlation_coefficient(dist1, Digiproc::Functions.process(dist1, ->(x){x * -2 + 3} ))
|
|
20
|
+
|
|
21
|
+
puts "Correlation coefficient, different random distributions: #{corr_coeff}"
|
|
22
|
+
puts "Correlation coefficient, gain and shifted from same distribution #{corr_coeff_2}"
|
|
23
|
+
puts
|
|
24
|
+
|
|
25
|
+
# stddev, mean, variance, covariance, cdf, q, pdf
|
|
26
|
+
|
|
27
|
+
distribution = Digiproc::Probability::RealizedGaussianDistribution.new(mean: 0, stddev: 10, size: 100).data
|
|
28
|
+
|
|
29
|
+
mean = pfuncs.mean(distribution)
|
|
30
|
+
stddev = pfuncs.stddev(distribution)
|
|
31
|
+
variance = pfuncs.variance(distribution)
|
|
32
|
+
cov = pfuncs.covariance(distribution, distribution)
|
|
33
|
+
pdf = pfuncs.pdf(distribution)
|
|
34
|
+
cdf = pfuncs.normal_cdf(5, mean, stddev)
|
|
35
|
+
q = pfuncs.normal_q(5, mean, stddev)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
puts "Mean: #{mean}"
|
|
39
|
+
puts "Std. Deviation: #{stddev}"
|
|
40
|
+
puts "Variance: #{variance}"
|
|
41
|
+
puts "Covaraince: #{cov}"
|
|
42
|
+
# puts "PDF: #{pdf}" => Long print - a big hash of value => occurances count
|
|
43
|
+
puts "CDF of 5, at mean: #{mean}, stddev: #{stddev}: #{cdf}"
|
|
44
|
+
puts "Q of 5, at mean: #{mean}, stddev: #{stddev}: #{q}"
|
|
45
|
+
puts
|
|
46
|
+
puts
|
|
47
|
+
|
|
48
|
+
# linspace(start, stop, num_points)
|
|
49
|
+
|
|
50
|
+
t = Digiproc::Functions.linspace(0, 5, 10)
|
|
51
|
+
puts "Linspace from 0 to 5, 10 numbers"
|
|
52
|
+
puts t.to_s
|
|
53
|
+
puts
|
|
54
|
+
|
|
55
|
+
# factorial (includes memoization, you can build memory to allow fact of larger numbers by incrementing fact size)
|
|
56
|
+
|
|
57
|
+
fns = Digiproc::Functions
|
|
58
|
+
puts "Factorial of 23: #{fns.fact(23)}"
|
|
59
|
+
puts
|
|
60
|
+
|
|
61
|
+
# process(vals, eqn) processes values with an equation
|
|
62
|
+
|
|
63
|
+
eqn = ->(x){ x ** 2 }
|
|
64
|
+
vals = [1,2,3,4,5,6]
|
|
65
|
+
out = fns.process(vals, eqn)
|
|
66
|
+
puts "Output of process: #{out}"
|
|
67
|
+
puts
|
|
68
|
+
puts
|
|
69
|
+
|
|
70
|
+
# maxima, local maxima (relative maxima in order (forward and reverse) -> useful when trying to find local maxima in a fft plot
|
|
71
|
+
# where signals of interest are local maxima not absolute maxima)
|
|
72
|
+
|
|
73
|
+
vals = [1,2,3,4,5,6,5,4,5,4,3,2,5,2,3,4,3,2,3,4,9,6,7,8,7,1]
|
|
74
|
+
|
|
75
|
+
maxima = fns.maxima(vals)
|
|
76
|
+
top_three_maxima = fns.maxima(vals, 3)
|
|
77
|
+
local_maximas = fns.local_maxima(vals, 3)
|
|
78
|
+
|
|
79
|
+
puts "Maxima: #{maxima}"
|
|
80
|
+
puts "Top 3 maxima: #{top_three_maxima}"
|
|
81
|
+
puts "Local maxima (3): #{local_maximas}"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Attempt to solve a system of linear equations using these strategies
|
|
2
|
+
|
|
3
|
+
a = [[2,-3,0],[1,3,-10],[3,0,1]]
|
|
4
|
+
b = [-7,9,13]
|
|
5
|
+
|
|
6
|
+
js = Digiproc::Strategies::JacobiStrategy.new(a,b)
|
|
7
|
+
gs = Digiproc::Strategies::GaussSeidelStrategy.new(a,b)
|
|
8
|
+
sor = Digiproc::Strategies::Sor2Strategy.new(a,b)
|
|
9
|
+
|
|
10
|
+
puts js.calculate
|
|
11
|
+
puts gs.calculate
|
|
12
|
+
puts sor.calculate(w: 0.1)
|
|
13
|
+
puts (Matrix.rows(a).inv * Matrix.column_vector(b)).map(&:to_f)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Iteratively solve a system of linear equations using these strategies
|
|
2
|
+
|
|
3
|
+
a = [[10,4,0,0],[0,7,0,3],[9,0,8,1],[1,0,0,1]]
|
|
4
|
+
b = [52,24,61,5]
|
|
5
|
+
|
|
6
|
+
js = Digiproc::Strategies::JacobiStrategy.new(a,b)
|
|
7
|
+
gs = Digiproc::Strategies::GaussSeidelStrategy.new(a,b)
|
|
8
|
+
sor = Digiproc::Strategies::SorStrategy.new(a,b)
|
|
9
|
+
|
|
10
|
+
puts js.calculate
|
|
11
|
+
puts gs.calculate
|
|
12
|
+
puts sor.calculate(w: 0.5)
|
|
13
|
+
puts (Matrix.rows(a).inv * Matrix.column_vector(b)).map(&:to_f)
|
|
14
|
+
|
|
15
|
+
a = [
|
|
16
|
+
[1,-1,-1,-1,-1,-1],
|
|
17
|
+
[-1,2,0,0,0,0],
|
|
18
|
+
[-1,0,3,1,1,1],
|
|
19
|
+
[-1,0,1,4,2,2],
|
|
20
|
+
[-1,0,1,2,5,3],
|
|
21
|
+
[-1,0,1,2,3,6]
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
b = [-4,1,5,8,10,11]
|
|
25
|
+
|
|
26
|
+
sor = Digiproc::Strategies::SorStrategy.new(a,b)
|
|
27
|
+
puts sor.calculate(w: 0.5, threshold: 0.000001)
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Show that PSK and DPSK modulated signals have the same bandwidth
|
|
2
|
+
|
|
3
|
+
# Define DPSK encoding/decoding strategy
|
|
4
|
+
dpsk_strategy = Digiproc::Strategies::XORDifferentialEncodingZeroAngleStrategy
|
|
5
|
+
|
|
6
|
+
# *********** NOTE: Digiproc::Strategies::DifferentialEncodingStrategy encodes for an M-ary PSK signal, requires decoding
|
|
7
|
+
# via reciever in figure 4-15 of INTRODUCITON TO DIGITAL COMMUNICATION, ZIEMER, PETERSON which has not been implemented.
|
|
8
|
+
|
|
9
|
+
# Not adding a coding strategy into PSK causes bit to phase mapping to not be differentially encoded
|
|
10
|
+
|
|
11
|
+
# Make a 100-bit stream, make one PSK (Phase Shift Keying) and one DPSK (Differential PSK) signal, plot the frequency domians
|
|
12
|
+
|
|
13
|
+
signal2 = Digiproc::Probability::RandomBitGenerator.new_bitstream.generate(600).split('')
|
|
14
|
+
psk2 = Digiproc::Strategies::PSK.new(modulating_signal: signal2, carrier_frequency: 10, pulse_length: 0.05)
|
|
15
|
+
dpsk2 = Digiproc::Strategies::PSK.new(modulating_signal: signal2, coding_strategy: dpsk_strategy, carrier_frequency: 10, pulse_length: 0.05)
|
|
16
|
+
|
|
17
|
+
puts "PSK Signal"
|
|
18
|
+
puts "Coded"
|
|
19
|
+
puts psk2.coded_signal.to_s
|
|
20
|
+
puts "Phase"
|
|
21
|
+
puts psk2.phase_signal.to_s
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
puts "DPSK Signal"
|
|
25
|
+
puts "Coded"
|
|
26
|
+
puts dpsk2.coded_signal.to_s
|
|
27
|
+
puts "Phase"
|
|
28
|
+
puts dpsk2.phase_signal.to_s
|
|
29
|
+
|
|
30
|
+
puts "Original signal:"
|
|
31
|
+
puts "#{signal2}"
|
|
32
|
+
puts "Decoded signal:"
|
|
33
|
+
# NOTE: decoded signals are not simulating a reciever, but just reversing the coding strategy
|
|
34
|
+
puts "DPSK"
|
|
35
|
+
puts "#{dpsk2.decode}"
|
|
36
|
+
puts "PSK"
|
|
37
|
+
puts "#{psk2.decode}"
|
|
38
|
+
puts "Match check"
|
|
39
|
+
puts "DPSK decode matches original:"
|
|
40
|
+
puts signal2 == dpsk2.decode
|
|
41
|
+
puts "PSK decode matches original:"
|
|
42
|
+
puts signal2 == psk2.decode.map{ |i| i.to_i.to_s }
|
|
43
|
+
|
|
44
|
+
# Below simulates a receiver per fig. 4-14 in INTRODUCTION TO DIGITAL COMMUNICATIONS, ZIEMER, PETERSON
|
|
45
|
+
# Reciever is of the form: phase signal -> Bandwidth Filter 0.57 / Tb -> Delay -> multiply -> Lowpass Filter -> Sample at t = Tb -> Output
|
|
46
|
+
#|-bypass-->{up_arrow}
|
|
47
|
+
|
|
48
|
+
#Example below fails, if you have time and want to help troubleshoot, please contribute! First
|
|
49
|
+
# 200 samples are showing up, and the rest seem to be wrapped in the front of the ifft. See
|
|
50
|
+
# Digiproc::Strategies::PSK#reciever_out for troubleshooting
|
|
51
|
+
|
|
52
|
+
puts "Simulated DPSK reciever output:"
|
|
53
|
+
receiver_out = dpsk2.reciever_decode
|
|
54
|
+
puts receiver_out.to_s
|
|
55
|
+
puts receiver_out.map{ |i| i.to_f <=> 0 }.map{ |i| i == -1 ? 0 : 1 }.to_s
|
|
56
|
+
puts "Test equality of signal"
|
|
57
|
+
test_sig = receiver_out.map{ |i| (i.to_f <=> 0).to_s }.map{ |i| i == "-1" ? "0" : "1" }
|
|
58
|
+
|
|
59
|
+
# Note - this reciever only works for small signals at this time.
|
|
60
|
+
# The FFT funciton needs to be optimized to automatically set the appropriate size
|
|
61
|
+
# based off of the input function
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
puts test_sig.size
|
|
66
|
+
puts signal2.size
|
|
67
|
+
puts test_sig == signal2
|
|
68
|
+
puts test_sig == signal2.take(test_sig.length)
|
|
69
|
+
|
|
70
|
+
test_sig.each_with_index do |sym, i|
|
|
71
|
+
if test_sig[i] != signal2[i]
|
|
72
|
+
puts "Signal fails at index #{i}"
|
|
73
|
+
puts signal2[i - 10, 50].to_s
|
|
74
|
+
puts test_sig[i - 10, 50].to_s
|
|
75
|
+
break
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
path = "./examples/modulation_schemes/"
|
|
80
|
+
|
|
81
|
+
Digiproc::QuickPlot.plot(data: psk2.output.to_ds.fft.magnitude, title: "PSK 2", path: path)
|
|
82
|
+
Digiproc::QuickPlot.plot(data: dpsk2.output.to_ds.fft.magnitude, title: "DPSK 2", path: path)
|
|
83
|
+
|
|
84
|
+
# Make 75 8-bit symbols, make one PSK and one DPSK signal, plot the frequency domians
|
|
85
|
+
signal256 = Digiproc::Probability::RandomBitGenerator.new_symbol_stream(bits_per_symbol: Math.log(256,2).to_i).generate 75
|
|
86
|
+
psk256 = Digiproc::Strategies::PSK.new(modulating_signal: signal256, carrier_frequency: 10, pulse_length: 0.4)
|
|
87
|
+
dpsk256 = Digiproc::Strategies::PSK.new(modulating_signal: signal256, coding_strategy: dpsk_strategy ,carrier_frequency: 10, pulse_length: 0.4)
|
|
88
|
+
s = signal256.map{|a| a.to_i(2)}
|
|
89
|
+
|
|
90
|
+
puts "Original signal"
|
|
91
|
+
puts s.to_s
|
|
92
|
+
puts
|
|
93
|
+
puts "DPSK Signal"
|
|
94
|
+
puts "Coded"
|
|
95
|
+
puts dpsk256.coded_signal.to_s
|
|
96
|
+
puts "Phase"
|
|
97
|
+
puts dpsk256.phase_signal.to_s
|
|
98
|
+
puts
|
|
99
|
+
puts "PSK Signal"
|
|
100
|
+
puts "Coded"
|
|
101
|
+
puts psk256.coded_signal.to_s
|
|
102
|
+
puts "Phase"
|
|
103
|
+
puts psk256.phase_signal.to_s
|
|
104
|
+
|
|
105
|
+
Digiproc::QuickPlot.plot(data: psk256.output.to_ds.fft.magnitude, title: "PSK 256", path: path)
|
|
106
|
+
Digiproc::QuickPlot.plot(data: dpsk256.output.to_ds.fft.magnitude, title: "DPSK 256", path: path)
|
|
107
|
+
|
|
108
|
+
puts "Original Signal"
|
|
109
|
+
puts "#{signal256}"
|
|
110
|
+
|
|
111
|
+
puts "Decoded signal"
|
|
112
|
+
puts "Decoded DPSK"
|
|
113
|
+
puts "#{dpsk256.decode}"
|
|
114
|
+
puts "Decoded PSK"
|
|
115
|
+
puts "#{psk256.decode}"
|
|
116
|
+
|
|
117
|
+
puts "Match check:"
|
|
118
|
+
puts "#{signal256 == dpsk256.decode}"
|
|
119
|
+
puts "#{signal256 == psk256.decode.map{ |i| i.to_i.to_s }}"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
plt = Digiproc::QuickPlot
|
|
2
|
+
|
|
3
|
+
sig_str = "110100010110"
|
|
4
|
+
sig = sig_str.split('')
|
|
5
|
+
diff_sig = Digiproc::Strategies::XORDifferentialEncodingStrategy.encode(sig, 2, "0")
|
|
6
|
+
|
|
7
|
+
bpsk = Digiproc::Strategies::PSK.new(modulating_signal: diff_sig, coding_strategy: nil)
|
|
8
|
+
bdpsk = Digiproc::Strategies::PSK.new(modulating_signal: sig)
|
|
9
|
+
dpsk = Digiproc::Strategies::PSK.new(modulating_signal: sig, coding_strategy: Digiproc::Strategies::DifferentialEncodingStrategy)
|
|
10
|
+
|
|
11
|
+
puts "System 1 Differential Signal: #{bpsk.coded_signal}"
|
|
12
|
+
puts "System 1 Phase: #{bpsk.phase_signal.map{ |ps| ps / Math::PI }} * pi"
|
|
13
|
+
puts "System 1 Decoded: #{bpsk.decode}"
|
|
14
|
+
plt.plot(data: bpsk.phase_signal.map{ |p| p / Math::PI}, y_label: "Phase", title: "System 1 Phase")
|
|
15
|
+
puts "\n\n"
|
|
16
|
+
puts "System 2 Differential Signal: #{bdpsk.coded_signal}"
|
|
17
|
+
puts "System 2 Coded Phase: #{bdpsk.phase_signal.map{ |ps| ps / Math::PI}} * pi"
|
|
18
|
+
puts "System 2 Decoded: #{bdpsk.decode}"
|
|
19
|
+
plt.plot(data: bdpsk.phase_signal.map{ |p| p / Math::PI},y_label: "Phase", title: "System 2 Phase")
|
|
20
|
+
puts "\n\n"
|
|
21
|
+
|
|
22
|
+
puts "System 3 Signal: #{dpsk.coded_signal}"
|
|
23
|
+
puts "System 3 Coded Phase: #{dpsk.phase_signal.map{ |p| p / Math::PI}} * pi"
|
|
24
|
+
puts "System 3 Decoded: #{dpsk.decode}"
|
|
25
|
+
plt.plot(data: dpsk.phase_signal.map{ |p| p / Math::PI},y_label: "Phase", title: "System 3 Phase")
|
|
26
|
+
puts "\n\n"
|
|
27
|
+
|
|
28
|
+
# dpsk_output = dpsk.output
|
|
29
|
+
# time_range = Digiproc::Functions.linspace(0, dpsk_output.sample_rate * dpsk_output.size, dpsk_output.size)
|
|
30
|
+
path = "./examples/modulation_schemes/"
|
|
31
|
+
plt.plot(data: bpsk.output.digitize, title: "System 1 Xmit Signal", y_label: "Magnitude", dark: true, path: path)
|
|
32
|
+
plt.plot(data: bdpsk.output.digitize, title: "System 2 Xmit Signal", y_label: "Magnitude", dark: true, path: path)
|
|
33
|
+
plt.plot(data: dpsk.output.digitize, title: "System 3 Xmit Signal", y_label: "Magnitude", dark: true, path: path)
|
|
34
|
+
puts "System 1 Output From Reciever: \n#{bpsk.reciever_decode}\n\n"
|
|
35
|
+
puts "System 2 Output From Reciever: \n#{bdpsk.reciever_decode}\n\n"
|
|
36
|
+
puts "System 3 Output From Reciever: \n#{dpsk.reciever_decode}\n\n"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# DISREGARD THIS EXAMPLE
|
|
2
|
+
|
|
3
|
+
#Using Gruff Line
|
|
4
|
+
|
|
5
|
+
#Below does not work, needs to be re-worked
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
g = Gruff::Line.new('1000x1000')
|
|
9
|
+
distr = Digiproc::Probability::RealizedGaussianDistribution.new(mean: 0, stddev: 3, size: 100)
|
|
10
|
+
g.data :random, distr.data
|
|
11
|
+
gnew = Digiproc::Plottable::ClassMethods::VerticalLine.new(g, 30)
|
|
12
|
+
gnew.write('./examples/quickplot/test.png')
|
|
13
|
+
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Use gruff directly
|
|
2
|
+
g = Gruff::Line.new('1000x1000')
|
|
3
|
+
distr = Digiproc::Probability::GaussianDistribution.new(mean: 0, stddev: 3, size: 100)
|
|
4
|
+
g.data("Random data", distr.data)
|
|
5
|
+
g.write('./examples/quickplot/direct_gruff.png')
|
|
6
|
+
|
|
7
|
+
path = "./examples/quickplot/"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Using QuickPlot
|
|
11
|
+
|
|
12
|
+
plt = Digiproc::QuickPlot
|
|
13
|
+
plt.plot(title: "Random data QuickPlot", data: distr.data, path: path, data_name: "Random distr.")
|
|
14
|
+
plt.plot(title: "Random data QuickPlot, dark", data: distr.data, path: path, x_label: "x axis", y_label: "y axis",dark: true)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Using Plottable Module inside a class
|
|
21
|
+
|
|
22
|
+
# Big advantage of not using QuickPlot is the ability to use xsteps as a parameter which specifies the label
|
|
23
|
+
# interval on the x axis of the plot
|
|
24
|
+
class PlottableClass
|
|
25
|
+
|
|
26
|
+
extend Digiproc::Plottable::ClassMethods
|
|
27
|
+
include Digiproc::Plottable::InstanceMethods
|
|
28
|
+
|
|
29
|
+
def initialize(distr)
|
|
30
|
+
@distr = distr
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def data
|
|
34
|
+
return @distr.data
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
plot = PlottableClass
|
|
40
|
+
|
|
41
|
+
plot.qplot(data: distr.data, data_name: "Random distribution",xsteps: 10, path: path) do |g|
|
|
42
|
+
g.title = "Random Data Plottable qPlot"
|
|
43
|
+
g.x_axis_label = "x axis"
|
|
44
|
+
g.y_axis_label = "y axis"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
plot_instance = PlottableClass.new(distr)
|
|
48
|
+
|
|
49
|
+
# Instnace Methods includes qplot which is the same as above
|
|
50
|
+
# plot used below should be renamed to fftPlot() - it was created to plot
|
|
51
|
+
# a Discrete Fourier Transform - the x axis goes from 0 to 1 regardless of
|
|
52
|
+
# points in the dataset to correspond to normalized frequency in a DFT plot.
|
|
53
|
+
|
|
54
|
+
plot_instance.plot(method: :data, xsteps: 10, path: path) do |g|
|
|
55
|
+
g.title = "Random Data from Instance Method"
|
|
56
|
+
g.x_axis_label = "x axis"
|
|
57
|
+
g.y_axis_label = 'y axis'
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## You can use Digiproc::Plottable class methods as well: (TODO)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
## Using Rbplot
|
|
66
|
+
|
|
67
|
+
x = Digiproc::Functions.linspace(1,100,100)
|
|
68
|
+
y1 = Digiproc::Probability.nrand(100)
|
|
69
|
+
y2 = Digiproc::Probability.nrand(100)
|
|
70
|
+
|
|
71
|
+
plt = Digiproc::Rbplot.line(x,y1)
|
|
72
|
+
plt.size(2000,2000)
|
|
73
|
+
plt.title('Test title')
|
|
74
|
+
plt.xlabel('x axis')
|
|
75
|
+
plt.ylabel('y axis')
|
|
76
|
+
plt.xsteps(10)
|
|
77
|
+
plt.add_line(x, y2)
|
|
78
|
+
plt.add_line(x,x.map{ |a| a / 100})
|
|
79
|
+
plt.theme(:light)
|
|
80
|
+
plt.legend('set1', 'set2', 'set3')
|
|
81
|
+
plt.show
|
|
82
|
+
plt.title('Test title dark')
|
|
83
|
+
plt.theme(:dark)
|
|
84
|
+
plt.show
|
|
85
|
+
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
plt = Dsp::QuickPlot
|
|
2
|
+
gauss = Dsp::Probability::RealizedGaussianDistribution
|
|
3
|
+
fns = Dsp::Functions
|
|
4
|
+
|
|
5
|
+
distribution = gauss.new(mean: 0, stddev: 10, size: 100)
|
|
6
|
+
data = distribution.data
|
|
7
|
+
|
|
8
|
+
#qplot function in quickplot gives a different plot API
|
|
9
|
+
plt.qplot(data: data, path: './examples/realized_gaussian/', filename: 'norm_dist_plot', xsteps: 10, data_name: "normal random numbers") do |g|
|
|
10
|
+
g.title = "Gaussian Random Numbers"
|
|
11
|
+
g.theme = Dsp::Plottable::Styles::MIDNIGHT
|
|
12
|
+
g.show_vertical_markers = false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
spectra = fns.fft(data).map(&:abs)
|
|
16
|
+
x_vals = fns.linspace(0,128,128)
|
|
17
|
+
|
|
18
|
+
plt.qplot(data: spectra, path: './examples/realized_gaussian/', filename: 'norm_dist_spectrum', xsteps: 4, xyname: "spectra mag. of norm. random nums") do |g|
|
|
19
|
+
g.title = "Gaussian Nums: Frequency Domain"
|
|
20
|
+
g.labels = {0 => 0, 32 => 0.25, 64 => 0.5, 98 => 0.75, 127 => 1}
|
|
21
|
+
g.show_vertical_markers = false
|
|
22
|
+
end
|
|
23
|
+
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
|
|
2
|
+
module Digiproc::Convolvable
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# This module contains class methods for performing convolution based off a strategy. Digiproc::Convolvable
|
|
7
|
+
# extends ClassMethods, and therefore all methods can be called on the Convolable module.
|
|
8
|
+
# Note that arrays in this module must be of Numeric types
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
##
|
|
12
|
+
## convolve(data1 [Array], data2 [Array], strategy [ConvolutionStrategy]) => returns Array[Numeric]
|
|
13
|
+
# This method performs convolution.
|
|
14
|
+
# `strategy` can be custom-written as long as it matches the ConvolutionStrategy interface:
|
|
15
|
+
# have a class method called `conv` which takes 2 arrays and convolves them. ie:
|
|
16
|
+
## Digiproc::Convolvable.conv([1,2,3],[1,2,3]) #=> [1, 4, 10, 12, 9]
|
|
17
|
+
|
|
18
|
+
def convolve(data1, data2, strategy = Digiproc::Strategies::BFConvolutionStrategy)
|
|
19
|
+
strategy.conv(data1, data2, strategy)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Alias to #convolve
|
|
24
|
+
def conv(data1, data2, strategy = Digiproc::Strategies::BFConvolutionStrategy)
|
|
25
|
+
strategy.conv(data1,data2)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
## cross_correlation(data1 [Array], data2 [Array]) => returns Array[Numeric]
|
|
30
|
+
# Uses the #conv method to perform cross_correlation by reversing the second data set order
|
|
31
|
+
# Does not accept a strategy as a third parameter
|
|
32
|
+
## Digiproc::Convolvable.cross_correlation(arr1, arr2)
|
|
33
|
+
def cross_correlation(data1, data2)
|
|
34
|
+
conv(data1, data2.reverse)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Alias to #cross_correlation
|
|
39
|
+
def xcorr(data1, data2)
|
|
40
|
+
cross_correlation(data1, data2)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
## auto_correlation(data [Array]) => returns Array[Numeric]
|
|
45
|
+
# Uses the cross_correlation method to perform cross correlation of data on itself.
|
|
46
|
+
## Digiproc::Convolvable.auto_correlation([1,2,3]) # => [3, 8, 14, 8, 3]
|
|
47
|
+
def auto_correlation(data)
|
|
48
|
+
cross_correlation(data, data)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Alias to #auto_correlation
|
|
54
|
+
# ie:
|
|
55
|
+
## Digiproc::Convolvable.acorr([1,2,3]) # => [3, 8, 14, 8, 3]
|
|
56
|
+
def acorr(data)
|
|
57
|
+
cross_correlation(data, data)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# This module contains instance methods for classes which have properties of `data` which
|
|
64
|
+
# are arrays and can undergo convolution, correlation, cross-correlation, and autocorrelation (arrays must then be of Numerics). As such, if
|
|
65
|
+
# a class `includes` Convolvable::InstanceMethods, it is also including `Digiproc::RequiresData` which ensures that the
|
|
66
|
+
# class has a `data` property
|
|
67
|
+
|
|
68
|
+
module InstanceMethods
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# When included in a class, it automatically has that class include Digiproc::RequiresData, because methods in this module require that there be a property called `data` which is an Array
|
|
72
|
+
def self.included(base)
|
|
73
|
+
base.class_eval do
|
|
74
|
+
include Digiproc::RequiresData
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
# Optionally initializable with a `ConvolutionStrategy` (see `Digiproc::Initializable`)
|
|
80
|
+
# This snows up as new, but when using this code, :initialize will be called. This pattern is utilized in the Digiproc::DigitalSignal class, and can be seen in its initializer.
|
|
81
|
+
def initialize(strategy: Digiproc::Strategies::BFConvolutionStrategy)
|
|
82
|
+
@convolution_strategy = strategy
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
##
|
|
86
|
+
## convolve(incoming_data [Array [OR a class including Digiproc::RequiresData]]) => returns Array[Numeric]
|
|
87
|
+
# uses the `strategy` class to convolve the included class' data property with the array provided as an argument
|
|
88
|
+
# ie if class DataHolder includes Convolavable::InstanceMethods, and you have two instances, d1 and d2, you can say:
|
|
89
|
+
## d1.convolve(d2)
|
|
90
|
+
# Or, if you have a 1D array of numerics in variable `my_data_arr` capable of convolving with d1.data, you can say:
|
|
91
|
+
## d1.convolve(my_data_arr) # returns array of data
|
|
92
|
+
def convolve(incoming_data)
|
|
93
|
+
incoming_data = incoming_data.is_a?(Array) ? incoming_data : incoming_data.data
|
|
94
|
+
self.convolution_strategy.conv(self.data, incoming_data)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
##
|
|
98
|
+
# Alias to convolve
|
|
99
|
+
def conv(incoming_data)
|
|
100
|
+
self.convolve(incoming_data)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# Used internally to ensure that if the class which includes this module is not `Initializable`, then a Convolution strategy will still be set
|
|
105
|
+
# In this case, use Digiproc::BFConvolutionStrategy
|
|
106
|
+
def convolution_strategy
|
|
107
|
+
@convolution_strategy.nil? ? Digiproc::Strategies::BFConvolutionStrategy : @convolution_strategy
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
##
|
|
111
|
+
## cross_correlation(incoming_data [Array [OR a class extending Digiproc::RequiresData]]) => returns Array[Numeric]
|
|
112
|
+
# see #convolve for example of using an array or a Digiproc::RequiresData. ie:
|
|
113
|
+
## includingInstance.cross_correlation(array_data) # returns array of data
|
|
114
|
+
def cross_correlation(incoming_data)
|
|
115
|
+
incoming_data = incoming_data.is_a?(Array) ? incoming_data : incoming_data.data
|
|
116
|
+
self.convolution_strategy.conv(self.data, incoming_data.reverse)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# Alias to cross_correlation
|
|
121
|
+
def xcorr(incoming_data)
|
|
122
|
+
self.cross_correlation(incoming_data)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
## auto_correlation() => returns Array[Numeric]
|
|
127
|
+
# Performs autocorrelation of self.data ie:
|
|
128
|
+
## includingInstance.auto_correlation # returns array of data
|
|
129
|
+
def auto_correlation
|
|
130
|
+
self.cross_correlation(self.data)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
##
|
|
134
|
+
# Alias to auto_correlation
|
|
135
|
+
def acorr
|
|
136
|
+
self.cross_correlation(self.data)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
extend self::ClassMethods
|
|
143
|
+
|
|
144
|
+
end
|