digiproc 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +48 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +78 -0
  10. data/Rakefile +37 -0
  11. data/TODO.md +50 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/config/environment.rb +118 -0
  15. data/console_tests.rb +44 -0
  16. data/digiproc.gemspec +49 -0
  17. data/examples/analog_signals/analog_to_digital.rb +31 -0
  18. data/examples/analog_signals/companded-signals.png +0 -0
  19. data/examples/analog_signals/companding.rb +68 -0
  20. data/examples/analog_signals/fft-plot.png +0 -0
  21. data/examples/analog_signals/plot_Digiproc::FFT.png +0 -0
  22. data/examples/analog_signals/plot_Dsp::FFT.png +0 -0
  23. data/examples/analog_signals/quantization-outputs.png +0 -0
  24. data/examples/analog_signals/quantize_compand.rb +69 -0
  25. data/examples/binomial_distribution/bit_error.rb +14 -0
  26. data/examples/binomial_distribution/dice.rb +35 -0
  27. data/examples/digital_signals/_coded_frequency_signal,_ts_=_1_s.png +0 -0
  28. data/examples/digital_signals/_coded_frequency_signal,_ts_=_2_s.png +0 -0
  29. data/examples/digital_signals/coded_power_spectral_density,__ts_=_1_s.png +0 -0
  30. data/examples/digital_signals/coded_power_spectral_density,__ts_=_2_s.png +0 -0
  31. data/examples/digital_signals/coded_time_signal,_ts_=_1_s.png +0 -0
  32. data/examples/digital_signals/coded_time_signal,_ts_=_2_s.png +0 -0
  33. data/examples/digital_signals/freq_sig_from_eqn,_ts_=_1_s.png +0 -0
  34. data/examples/digital_signals/freq_sig_from_eqn,_ts_=_2_s.png +0 -0
  35. data/examples/digital_signals/frequency_signal,_ts_=_1_s.png +0 -0
  36. data/examples/digital_signals/frequency_signal,_ts_=_2_s.png +0 -0
  37. data/examples/digital_signals/modulate_square_pulses.rb +9 -0
  38. data/examples/digital_signals/modulated_sq._pulses.png +0 -0
  39. data/examples/digital_signals/modulated_sq._pulses_alt.png +0 -0
  40. data/examples/digital_signals/power_spectral_density,__ts_=_1_s.png +0 -0
  41. data/examples/digital_signals/power_spectral_density,__ts_=_2_s.png +0 -0
  42. data/examples/digital_signals/square_signals.rb +90 -0
  43. data/examples/digital_signals/time_signal,_ts_=_1_s.png +0 -0
  44. data/examples/digital_signals/time_signal,_ts_=_2_s.png +0 -0
  45. data/examples/encoding/gray_code.rb +22 -0
  46. data/examples/encoding/psk.rb +91 -0
  47. data/examples/encoding/system_2_phase.png +0 -0
  48. data/examples/encoding/system_2_xmit_signal.png +0 -0
  49. data/examples/encoding/system_3_phase.png +0 -0
  50. data/examples/encoding/system_3_xmit_signal.png +0 -0
  51. data/examples/encoding/system_4_xmit_signal.png +0 -0
  52. data/examples/encoding/xor-dpsk-phase-signal-(sys1).png +0 -0
  53. data/examples/encoding/xor-dpsk-xmit-signal-(sys-1).png +0 -0
  54. data/examples/factories/Quickplot Graph.png +0 -0
  55. data/examples/factories/bandpass.rb +6 -0
  56. data/examples/fft/plot_Dsp::FFT.png +0 -0
  57. data/examples/fft/recieved_data_(time_domain).png +0 -0
  58. data/examples/fft/simple_fft_example.rb +47 -0
  59. data/examples/fft/unprocessed_fft.png +0 -0
  60. data/examples/filters/bandpass_filter.png +0 -0
  61. data/examples/filters/filter_a_signal.rb +38 -0
  62. data/examples/filters/white_noise_db_out_of_bp_filter.png +0 -0
  63. data/examples/filters/white_noise_mag_out_of_bp_filter.png +0 -0
  64. data/examples/filters/white_noise_spectra.png +0 -0
  65. data/examples/functions/compute_probability.rb +29 -0
  66. data/examples/functions/gram_schmidt.rb +10 -0
  67. data/examples/functions/minimize_energy.rb +29 -0
  68. data/examples/functions/orthoganalize.rb +18 -0
  69. data/examples/functions/simple_functions.rb +81 -0
  70. data/examples/linear_algebra/diverging_sys.rb +13 -0
  71. data/examples/linear_algebra/iterative_sys_of_eqns_methods.rb +27 -0
  72. data/examples/modulation_schemes/dpsk_2.png +0 -0
  73. data/examples/modulation_schemes/dpsk_256.png +0 -0
  74. data/examples/modulation_schemes/dpsk_freq_domain.rb +119 -0
  75. data/examples/modulation_schemes/psk.rb +36 -0
  76. data/examples/modulation_schemes/psk_2.png +0 -0
  77. data/examples/modulation_schemes/psk_256.png +0 -0
  78. data/examples/modulation_schemes/psksystem_1_xmit_signal.png +0 -0
  79. data/examples/modulation_schemes/psksystem_2_xmit_signal.png +0 -0
  80. data/examples/modulation_schemes/psksystem_3_xmit_signal.png +0 -0
  81. data/examples/modulation_schemes/system_1_xmit_signal.png +0 -0
  82. data/examples/modulation_schemes/system_2_xmit_signal.png +0 -0
  83. data/examples/modulation_schemes/system_3_xmit_signal.png +0 -0
  84. data/examples/quickplot/PlottableClass_plot.png +0 -0
  85. data/examples/quickplot/decorators.rb +13 -0
  86. data/examples/quickplot/direct_gruff.png +0 -0
  87. data/examples/quickplot/plot_PlottableClass.png +0 -0
  88. data/examples/quickplot/quickplot_vs_others.rb +85 -0
  89. data/examples/quickplot/random_data_quickplot,_dark.png +0 -0
  90. data/examples/quickplot/random_data_quickplot.png +0 -0
  91. data/examples/realized_gaussian/norm_dist_plot.png +0 -0
  92. data/examples/realized_gaussian/norm_dist_spectrum.png +0 -0
  93. data/examples/realized_gaussian/realized_gaussian_example.rb +23 -0
  94. data/lib/concerns/convolvable.rb +144 -0
  95. data/lib/concerns/data_properties.rb +223 -0
  96. data/lib/concerns/fourier_transformable.rb +178 -0
  97. data/lib/concerns/initializable.rb +43 -0
  98. data/lib/concerns/multipliable.rb +22 -0
  99. data/lib/concerns/os.rb +36 -0
  100. data/lib/concerns/plottable.rb +248 -0
  101. data/lib/concerns/requires_data.rb +8 -0
  102. data/lib/digiproc/version.rb +8 -0
  103. data/lib/digiproc.rb +2 -0
  104. data/lib/extensions/array_extension.rb +23 -0
  105. data/lib/extensions/core_extensions.rb +117 -0
  106. data/lib/factories/factories.rb +3 -0
  107. data/lib/factories/filter_factory.rb +83 -0
  108. data/lib/factories/window_factory.rb +22 -0
  109. data/lib/fft.rb +255 -0
  110. data/lib/filters/bandpass_filter.rb +43 -0
  111. data/lib/filters/bandstop_filter.rb +44 -0
  112. data/lib/filters/digital_filter.rb +59 -0
  113. data/lib/filters/highpass_filter.rb +27 -0
  114. data/lib/filters/lowpass_filter.rb +27 -0
  115. data/lib/functions.rb +221 -0
  116. data/lib/probability/binomial_distribution.rb +84 -0
  117. data/lib/probability/bit_generator.rb +94 -0
  118. data/lib/probability/gaussian_distribution.rb +29 -0
  119. data/lib/probability/probability.rb +234 -0
  120. data/lib/probability/theoretical_gaussian_distribution.rb +59 -0
  121. data/lib/quick_plot.rb +96 -0
  122. data/lib/rbplot.rb +219 -0
  123. data/lib/signals/analog_signal.rb +143 -0
  124. data/lib/signals/digital_signal.rb +181 -0
  125. data/lib/strategies/code/differential_encoding_strategy.rb +69 -0
  126. data/lib/strategies/code/gray_code.rb +75 -0
  127. data/lib/strategies/code/xor_differential_encoding_strategy.rb +100 -0
  128. data/lib/strategies/code/xor_differential_encoding_zero_angle_strategy.rb +103 -0
  129. data/lib/strategies/companding/custom_companding_strategy.rb +29 -0
  130. data/lib/strategies/convolution/bf_conv.rb +57 -0
  131. data/lib/strategies/fft/brute_force_dft_strategy.rb +31 -0
  132. data/lib/strategies/fft/inverse_fft_conjugate_strategy.rb +44 -0
  133. data/lib/strategies/fft/radix2_strategy.rb +84 -0
  134. data/lib/strategies/gaussian/gaussian_generator.rb +49 -0
  135. data/lib/strategies/linear_algebra/gauss_seidel_strategy.rb +90 -0
  136. data/lib/strategies/linear_algebra/jacobi_strategy.rb +81 -0
  137. data/lib/strategies/linear_algebra/sor2_strategy.rb +98 -0
  138. data/lib/strategies/linear_algebra/sor_strategy.rb +108 -0
  139. data/lib/strategies/modulation/phase_shift_keying_strategy.rb +96 -0
  140. data/lib/strategies/orthogonalize/gram_schmidt.rb +50 -0
  141. data/lib/strategies/strategies.rb +3 -0
  142. data/lib/strategies/window/blackman_window.rb +32 -0
  143. data/lib/strategies/window/hamming_window.rb +31 -0
  144. data/lib/strategies/window/hanning_window.rb +31 -0
  145. data/lib/strategies/window/kaiser_window.rb +27 -0
  146. data/lib/strategies/window/rectangular_window.rb +22 -0
  147. data/lib/strategies/window/window.rb +42 -0
  148. data/lib/systems/custom_system.rb +13 -0
  149. data/lib/systems/hilbert_transform.rb +6 -0
  150. data/lib/systems/matched_filter.rb +21 -0
  151. data/lib/systems/raised_cosine_filter.rb +11 -0
  152. data/lib/systems/system.rb +19 -0
  153. data/lib/systems/systems.rb +3 -0
  154. data/playground.rb +323 -0
  155. data/plots/_coded_frequency_signal,_ts_=_1_s.png +0 -0
  156. data/plots/_coded_frequency_signal,_ts_=_2_s.png +0 -0
  157. data/plots/coded_freq_sig_from_eqn,_ts_=_1_s.png +0 -0
  158. data/plots/coded_freq_sig_from_eqn,_ts_=_2_s.png +0 -0
  159. data/plots/coded_power_spectral_density,__ts_=_1_s.png +0 -0
  160. data/plots/coded_power_spectral_density,__ts_=_2_s.png +0 -0
  161. data/plots/coded_time_signal,_ts_=_1_s.png +0 -0
  162. data/plots/coded_time_signal,_ts_=_2_s.png +0 -0
  163. data/plots/dpsk_2.png +0 -0
  164. data/plots/freq_sig_from_eqn,_ts_=_1_s.png +0 -0
  165. data/plots/freq_sig_from_eqn,_ts_=_2_s.png +0 -0
  166. data/plots/frequency_signal,_ts_=_1_s.png +0 -0
  167. data/plots/frequency_signal,_ts_=_2_s.png +0 -0
  168. data/plots/power_spectral_density,__ts_=_1_s.png +0 -0
  169. data/plots/power_spectral_density,__ts_=_2_s.png +0 -0
  170. data/plots/psk_2.png +0 -0
  171. data/plots/time_signal,_ts_=_1_s.png +0 -0
  172. data/plots/time_signal,_ts_=_2_s.png +0 -0
  173. data/test-title-dark.png +0 -0
  174. data/test-title.png +0 -0
  175. metadata +322 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a9beaf357290bb8d1ddfb103b8d39614ce93539ead7353e2053faf8a3d3c36c3
4
+ data.tar.gz: cf4a4a6c03e78ef312109654871c294c372f22bd9437813f61de092ae9453f89
5
+ SHA512:
6
+ metadata.gz: 6891122f07044a1f0c20b424d5c16753f67ef4dbc71458ada887835bf39747d616bb6f1914a0c5d8fae155c1c74188daf601e88081c9922111ff11ec8b74f387
7
+ data.tar.gz: 5a39c3fdba680ce91dec8122f8d9fd48959bc9df550bdce413d2b8efabe67f6d0feab00919f360a1fb2247ad9e15c4399b0af86bf771da7d1c7c514d97e2a851
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.1
7
+ before_install: gem install bundler -v 1.16.6
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at micah.shute@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in digiproc.gemspec
6
+ gemspec
7
+ gem 'gruff'
8
+
data/Gemfile.lock ADDED
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ digiproc (0.1.0)
5
+ gruff (~> 0.7.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.1.2)
11
+ diff-lcs (1.3)
12
+ gruff (0.7.0)
13
+ rmagick (~> 2.13, >= 2.13.4)
14
+ method_source (0.9.2)
15
+ pry (0.12.2)
16
+ coderay (~> 1.1.0)
17
+ method_source (~> 0.9.0)
18
+ rake (10.5.0)
19
+ rdoc (6.1.1)
20
+ rmagick (2.16.0)
21
+ rspec (3.8.0)
22
+ rspec-core (~> 3.8.0)
23
+ rspec-expectations (~> 3.8.0)
24
+ rspec-mocks (~> 3.8.0)
25
+ rspec-core (3.8.0)
26
+ rspec-support (~> 3.8.0)
27
+ rspec-expectations (3.8.3)
28
+ diff-lcs (>= 1.2.0, < 2.0)
29
+ rspec-support (~> 3.8.0)
30
+ rspec-mocks (3.8.0)
31
+ diff-lcs (>= 1.2.0, < 2.0)
32
+ rspec-support (~> 3.8.0)
33
+ rspec-support (3.8.0)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ bundler
40
+ digiproc!
41
+ gruff
42
+ pry
43
+ rake (~> 10.0)
44
+ rdoc
45
+ rspec (~> 3.0)
46
+
47
+ BUNDLED WITH
48
+ 2.0.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 micahshute
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # Digiproc
2
+
3
+ Use Digiproc to perform a number of digital signal processing calculations. Easily represent digital and analog signals, find their Discrete Fourier Transform in O(n*lgn) time, and create various systems from filtering, modulation, encoding, etc. Digiproc also enables you to easily solve a wide range of probability and linear algebra-based problems.
4
+
5
+ Easily visualize data in a graphing API built on top of gruff.
6
+
7
+ See the `examples` folder as well as the `spec`s.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'digiproc'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install digiproc
24
+
25
+ If you are having trouble downloading the rmagick gem on OSX, try the following:
26
+
27
+ ```
28
+ brew uninstall imagemagick
29
+ brew install imagemagick@6
30
+ export PATH="/usr/local/opt/imagemagick@6/bin:$PATH"
31
+ brew link --force imagemagick@6
32
+ gem install rmagick
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ Graphing capabillity built on top of [gruff](https://github.com/topfunky/gruff) gem, which uses the [rMagick](https://rubygems.org/gems/rmagick/versions/2.15.4) gem and ImageMagick.
38
+
39
+ __Look at specs and the `examples` folder for examples on how to use these classes in calculations__
40
+
41
+ __Limitations to be aware of__:
42
+ - All signals must be causual -> negative values of n are not supported
43
+ - The FFT, as of now, uses a Radix 2 algorithm. So, the overall size must be a power of 2 - any dataset is zero-filled automatically to meet this necessity. This gives you less control over the exact size if needed and may cause slower runtimes (however the radix 2 algorithm is &#1012;(nlgn)). This zero-fill _will_ increase the resolution of the FFT output, however.
44
+ - All filter data and windows must have an even number of datapoints. If not, this will be done automatically. This is to facilitate the ability to create any type of filter using the windowing method. (Odd numbers of values can preclude certain types of filters)
45
+ - All filters are FIR and are implemented via the windowing method. Although you can get pretty good results depending on your application, this is an older method compared to the optimal Parks-McClellan algorithm.
46
+ - IIR Filter design is not included
47
+ - The quantization process in Digiproc::AnalogSignal maps an analog signal to -1 to 1 before quantizing the result. A floating point number is accurate up to 7 decimal places, so this process will cause unwanted ACTUAL quantization errors (not simulated quantization errors) for an amplitude range greater than $2 x 10^16$ (ie 20 Quadrillion)
48
+
49
+ This is still a work in progress. There are many usuable functions, and many that still require tuning. Functions tested in the `spec` file are very reliable.
50
+
51
+
52
+
53
+ __Run Examples__
54
+
55
+ Use ```rake examples:run[file]``` to run an example file to see how it works, ie: ```rake examples:run[binomial_distribution/dice]```
56
+
57
+
58
+ ## Development
59
+
60
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
61
+
62
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
63
+
64
+ ## Contributing
65
+
66
+ Bug reports and pull requests are welcome on GitHub at https://github.com/micahshute/digiproc.
67
+
68
+ There is a long list of intended actions in the `TODO.md` file. Tests (rspec) covers many core capabilities, but more need to be written to cover the entire gem.
69
+
70
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. That being said, negative feedback is always welcome.
71
+
72
+ ## License
73
+
74
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
75
+
76
+ ## Code of Conduct
77
+
78
+ Everyone interacting in the Digiproc project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/digiproc/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+
9
+ task :environment do
10
+ require_relative './config/environment'
11
+ end
12
+
13
+ desc "Test data structures in console environment"
14
+ task :console => :environment do
15
+ require 'pry'
16
+ pry.start
17
+ end
18
+
19
+ desc "Loads data for console tests, runs console"
20
+ task :console_tests => :environment do
21
+ require 'pry'
22
+ require_relative './console_tests.rb'
23
+
24
+ end
25
+
26
+ desc "Env playground, same as console tests but not for testing"
27
+ task :play => :environment do
28
+ require 'pry'
29
+ require_relative './playground.rb'
30
+ end
31
+
32
+ namespace :examples do
33
+ desc "run an example file"
34
+ task :run, [:file] => :environment do |task, args|
35
+ require_relative "./examples/#{args[:file]}.rb"
36
+ end
37
+ end
data/TODO.md ADDED
@@ -0,0 +1,50 @@
1
+ # TODOS
2
+
3
+ - [x] Change FFT `data` variable to hold fft vals instead of time domain vals.
4
+ - [x] Make FFT class `convolvable`
5
+
6
+ - [x] Make new convolution strategy to replace Brute Force (BF) strategy
7
+ - [ ] This is what the FFT is for -> So, instead, clean up the FFT to allow ease of multiplying 2 together at the length necessary to ensure convolution signal can be fully regained (ie FFT sizes are length that convolution would be (ie data1.length + data2.length - 1))
8
+ - [ ] Figure out how to deal with ifft having very small imaginary values
9
+ - [ ] Figure out how to deal with zero padding from Radix2 strategy in outputs.
10
+ - [x] Add Gaussian distribution generator
11
+ - [x] Add White noise generator
12
+ - [ ] Add `analytic signal` function
13
+ - [ ] In where? Used for bandpass signals
14
+ - [x] Implement Analog signal, allow custom sampling rate, include nyquist freq (based on freq or bandwidth)
15
+ - [x] Implement quantization
16
+ - [x] Allow companding techniques in quantization process
17
+ - [x] Look at using another graphical tool instead of gruff
18
+ - [x] Sticking with gruff for now
19
+ - [x] Ensure FFT class is fully disconnected from FFTStrategy (ie having to zero fill for Radix2)
20
+ - [x] Ensure custom strategies can be built and implemented
21
+ - [x] Same as above for companding strategies and window strategies
22
+ - [x] Add #process to digitalSignal and FFT which accepts a block and iterates through each item in `data`
23
+ - [ ] Consider making this a module `processible`, which `requires_data`
24
+ - [x] Look into using a better quantization strategy (right now mapping max <-> min to -1 <-> +1 is limited by floating point accuraccy for large ranges)
25
+ - [x] Move `#map_to` method from AnalogSignal and put it in Digiproc::Functions
26
+ - [ ] Investigate changing Digiproc to Digiproc
27
+ - [ ] Review / cleanup / investigate proper scope of methods in Digiproc::Functions
28
+ - [ ] If the `#map_to` methods are kept in Digiproc::Functions, remove them from `AnalogSignal`
29
+ - [x] Add IFFT, make FFT class multiplyable,
30
+ - [ ] test to ensure FFT multiplication equals convolution in the time domain
31
+ - [ ] Add Decorators to Digiproc::QuickPlot to allow vertical lines being added, and maybe color schemes too
32
+ - [x] Make an alternative name to `dot` which is confusing because it is not the dot product (it does not sum at the end)
33
+ - [ ] Add power_spectral_density, etc to FourierTransformable module
34
+ - [ ] Figure out why convolution in matlab runs as slow as here, but cross-correlation is much faster
35
+ - [ ] Make transition_width and bandwidth, wo, etc consistant in the filter part of the project (ie right now some are normalized frequencies from 0 to 1 and some are normalized frequencies in radians)
36
+ - [ ] Ensure both Arrays and Vectors are supported for all `data` properties
37
+ - [ ] Digiproc::AnalogSignal => sample_rate: to sample_interval:
38
+ - [ ] Fix Strategies for DifferentialEncoding (change psk to the one in the PSK class)
39
+ - [ ] Find out why the PSK Differnetial Decoder starts at time != 0
40
+ - [ ] Put the differential decoder in a different class (ie a decoding strategy)
41
+ - [ ] Make `DigitalFilter` convolvable, fourierTranformable
42
+ - [ ] Automatcially match FFT sizes
43
+ - [ ] Fix sizing for ifft, etc
44
+ - [ ] Fix output of ifft (ie small imaginary numbers)
45
+ - [ ] Ensure no freq domain inconsitancies with radian vs cycle^-1 units (ie inputs in functions should all be radians or hz)
46
+ - [ ] "INTRODUCTION TO DIGITAL COMMUNICATIONS, ZIEMER, PETERSON" -> pg 239 Figure 4-16 add reciever for M-ary PSK decoding
47
+ - [ ] Put DigitalSignal and Windows (and any other necessary functions not currently in) inside of the Digiproc Module
48
+ - [ ] Make a working VerticalLine (and other) plot decorators
49
+ - [ ] Make graphs visually similar across all APIs, make easier custom visual changes
50
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "digiproc"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,118 @@
1
+
2
+ require "bundler/setup"
3
+
4
+ Bundler.require(:default)
5
+
6
+ require 'matrix'
7
+ require 'ostruct'
8
+ #Namespace
9
+ require 'digiproc'
10
+
11
+
12
+ #Extensions
13
+ require './lib/extensions/core_extensions'
14
+
15
+ Array.include Digiproc::CoreExtensions::ArrayExtension::DotProduct
16
+ Array.include Digiproc::CoreExtensions::ArrayExtension::Sum
17
+ Array.include Digiproc::CoreExtensions::ArrayExtension::Multiply
18
+ Math.extend Digiproc::CoreExtensions::MathExtension::Decible
19
+ Vector.include Digiproc::CoreExtensions::VectorExtension::Projection::InstanceMethods
20
+ Vector.extend Digiproc::CoreExtensions::VectorExtension::Projection::ClassMethods
21
+ # Float.include Digiproc::CoreExtensions::FloatExtension::OddPatch
22
+ class Gruff::Base
23
+
24
+ def draw_label(x_offset, index)
25
+ return if @hide_line_markers
26
+ if !@labels[index].nil? && @labels_seen[index].nil?
27
+ y_offset = @graph_bottom + LABEL_MARGIN
28
+ y_offset += @label_stagger_height if ((index.respond_to? :odd?) && index.odd?)
29
+ label_text = labels[index].to_s
30
+ if label_text.size > @label_max_size
31
+ if @label_truncation_style == :trailing_dots
32
+ if @label_max_size > 3
33
+ # 4 because '...' takes up 3 chars
34
+ label_text = "#{label_text[0 .. (@label_max_size - 4)]}..."
35
+ end
36
+ else # @label_truncation_style is :absolute (default)
37
+ label_text = label_text[0 .. (@label_max_size - 1)]
38
+ end
39
+
40
+ end
41
+
42
+ if x_offset >= @graph_left && x_offset <= @graph_right
43
+ @d.fill = @font_color
44
+ @d.font = @font if @font
45
+ @d.stroke('transparent')
46
+ @d.font_weight = NormalWeight
47
+ @d.pointsize = scale_fontsize(@marker_font_size)
48
+ @d.gravity = NorthGravity
49
+ @d = @d.annotate_scaled(@base_image,
50
+ 1.0, 1.0,
51
+ x_offset, y_offset,
52
+ label_text, @scale)
53
+ end
54
+ @labels_seen[index] = 1
55
+ debug { @d.line 0.0, y_offset, @raw_columns, y_offset }
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ #Strategies
62
+ require './lib/strategies/strategies'
63
+ require './lib/strategies/fft/inverse_fft_conjugate_strategy'
64
+ require './lib/strategies/fft/brute_force_dft_strategy'
65
+ require './lib/strategies/fft/radix2_strategy'
66
+ require './lib/strategies/convolution/bf_conv'
67
+ require './lib/strategies/window/window'
68
+ require './lib/strategies/window/blackman_window'
69
+ require './lib/strategies/window/hamming_window'
70
+ require './lib/strategies/window/hanning_window'
71
+ require './lib/strategies/window/rectangular_window'
72
+ require './lib/strategies/companding/custom_companding_strategy'
73
+ require './lib/strategies/gaussian/gaussian_generator'
74
+ require './lib/strategies/orthogonalize/gram_schmidt'
75
+ require './lib/strategies/code/gray_code'
76
+ require './lib/strategies/code/differential_encoding_strategy'
77
+ require './lib/strategies/code/xor_differential_encoding_strategy'
78
+ require './lib/strategies/code/xor_differential_encoding_zero_angle_strategy'
79
+ require './lib/strategies/modulation/phase_shift_keying_strategy'
80
+ require './lib/strategies/linear_algebra/jacobi_strategy'
81
+ require './lib/strategies/linear_algebra/gauss_seidel_strategy'
82
+ require './lib/strategies/linear_algebra/sor_strategy'
83
+ require './lib/strategies/linear_algebra/sor2_strategy'
84
+
85
+ #Modules
86
+ require './lib/concerns/plottable'
87
+ require './lib/concerns/requires_data'
88
+ require './lib/concerns/initializable'
89
+ require './lib/concerns/convolvable'
90
+ require './lib/concerns/fourier_transformable'
91
+ require './lib/concerns/multipliable'
92
+ require './lib/concerns/data_properties'
93
+ require './lib/functions'
94
+ require './lib/probability/probability'
95
+ require './lib/concerns/os'
96
+
97
+
98
+
99
+ #Classes
100
+ require './lib/fft'
101
+ require './lib/signals/digital_signal'
102
+ require './lib/filters/digital_filter.rb'
103
+ require './lib/filters/lowpass_filter.rb'
104
+ require './lib/filters/highpass_filter.rb'
105
+ require './lib/filters/bandpass_filter.rb'
106
+ require './lib/filters/bandstop_filter.rb'
107
+ require './lib/signals/analog_signal'
108
+ require './lib/probability/gaussian_distribution'
109
+ require './lib/probability/theoretical_gaussian_distribution'
110
+ require './lib/probability/bit_generator'
111
+ require './lib/probability/binomial_distribution'
112
+ require './lib/quick_plot'
113
+ require './lib/rbplot'
114
+
115
+ #Factories
116
+ require './lib/factories/factories'
117
+ require './lib/factories/window_factory'
118
+ require './lib/factories/filter_factory'
data/console_tests.rb ADDED
@@ -0,0 +1,44 @@
1
+ # x1 = Digiproc::AnalogSignal.new(eqn: ->(t){ 8 * Math.cos(20 * Math::PI * t) }, sample_rate: 1.0 / 51.0, size: 6, quantization_bits: 4, quant_max: 8, quant_min: -8)
2
+ # x2 = Digiproc::AnalogSignal.new(eqn: ->(t){ Math.cos(20 * Math::PI * t) }, sample_rate: 1.0 / 51.0, size: 6, quantization_bits: 4, quant_max: 8, quant_min: -8)
3
+
4
+ # compression_eqn = ->(n){ n < 0 ? (-4 * ((-n) ** (1.0 / 3))) : (4 * n ** (1.0 / 3))}
5
+ # expansion_eqn =->(n){ n < 0 ? ((-1.0 / 64) * ((-n) ** 3)) : ((1.0 / 64) * n ** 3)}
6
+ # compander = CustomCompandingStrategy.new(compression_eqn, expansion_eqn)
7
+
8
+ # x3 = Digiproc::AnalogSignal.new(eqn: ->(t){ 8 * Math.cos(20 * Math::PI * t) }, sample_rate: 1.0 / 51.0, size: 6, quantization_bits: 4, quant_max: 8, quant_min: -8, companding_strategy: compander)
9
+ # x4 = Digiproc::AnalogSignal.new(eqn: ->(t){ Math.cos(20 * Math::PI * t) }, sample_rate: 1.0 / 51.0, size: 6, quantization_bits: 4, quant_max: 8, quant_min: -8, companding_strategy: compander)
10
+
11
+ # puts "x(1): "
12
+ # puts x1.digitize.to_s
13
+ # puts "Raw samples: #{x1.raw_samples}"
14
+ # puts "Normalized Quantization RMS Error: #{x1.normalized_quantization_rms_error.round(3)}"
15
+ # puts "\n\nx(2):"
16
+ # puts x2.digitize.to_s
17
+ # puts "Raw samples: #{x2.raw_samples}"
18
+ # puts "Normalized Quantization RMS Error: #{x2.normalized_quantization_rms_error.round(3)}"
19
+ # puts "\n\nx(1) with companding: "
20
+ # puts x3.digitize.to_s
21
+ # puts "Raw samples: #{x3.raw_samples}"
22
+ # puts "Normalized Quantization RMS Error: #{x3.normalized_quantization_rms_error.round(3)}"
23
+ # puts "\n\nx(2) with companding:"
24
+ # puts x4.digitize.to_s
25
+ # puts "Raw samples: #{x4.raw_samples}"
26
+ # puts "Normalized Quantization RMS Error: #{x4.normalized_quantization_rms_error.round(3)}"
27
+ # binding.pry
28
+
29
+ # signal = ->(t){Math.cos(2 * Math::PI * t)} #cos at 1 Hz
30
+ # sample_times = (0..1000).map{ |int| int / 100.0} #Sample for 10 seconds every 0.01 seconds (100 times per period over 10 periods)
31
+ # data = sample_times.map{ |time| signal.call(time) }
32
+ # ft = []
33
+ # for k in 0...data.length do
34
+ # tot = 0
35
+ # data.each_with_index do |x_n, n|
36
+ # tot += x_n * Math::E ** (Complex(0,-1) * 2.0 * Math::PI * k * n / data.length.to_f)
37
+ # end
38
+ # ft << tot
39
+ # end
40
+
41
+ # fft = Digiproc::FFT.new(data: data).calculate
42
+
43
+
44
+ binding.pry
data/digiproc.gemspec ADDED
@@ -0,0 +1,49 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "digiproc/version"
5
+
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = "digiproc"
9
+ spec.version = Digiproc::VERSION
10
+ spec.authors = ["micahshute"]
11
+ spec.email = ["micah.shute@gmail.com"]
12
+
13
+ spec.summary = %q{Perform basic Digital Signal Processing tasks, including convolution, fft, filtering.}
14
+ spec.description = %q{Allows design of digital signals using the FFT, design of Digital Filters using the Windowing Method, creation of Digital Signals or Analog Signals sampled at a certain interval, convolution, cross-correlation, and visualization of the data. .}
15
+ spec.homepage = "https://rubygems.org/gems/digiproc"
16
+ spec.license = "MIT"
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
22
+
23
+ spec.metadata["homepage_uri"] = spec.homepage
24
+ spec.metadata["source_code_uri"] = "https://github.com/micahshute/digiproc"
25
+ spec.metadata["changelog_uri"] = "https://github.com/micahshute/digiproc"
26
+ else
27
+ raise "RubyGems 2.0 or newer is required to protect against " \
28
+ "public gem pushes."
29
+ end
30
+
31
+ # Specify which files should be added to the gem when it is released.
32
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
33
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
34
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|png)/}) }
35
+ end
36
+ spec.bindir = "exe"
37
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
38
+ spec.require_paths = ["lib"]
39
+
40
+ spec.add_development_dependency "bundler"
41
+ spec.add_development_dependency "rake", "~> 10.0"
42
+ spec.add_development_dependency "rspec", "~> 3.0"
43
+ spec.add_development_dependency 'rdoc'
44
+ spec.add_development_dependency 'pry'
45
+ spec.add_development_dependency 'gruff', "~> 0.7.0"
46
+ spec.add_runtime_dependency "gruff", "~> 0.7.0"
47
+ # spec.add_dependency "gruff"
48
+ end
49
+
@@ -0,0 +1,31 @@
1
+ # Sample an analog signal, turn into digital signal and calculate the FFT
2
+ plt = Digiproc::QuickPlot
3
+ analog_signal_eqn = ->(t){ (t >= 0 and t <= 0.1) ? (100 * t * Math.cos(Math::PI*2.5*t)) : 0 }
4
+
5
+ analog_signal_eqn = ->(t){ Math.cos(2*Math::PI * 50 * t) + Math.cos(2 * Math::PI * 1250 * t) }
6
+
7
+ analog_signal = Digiproc::AnalogSignal.new(eqn: analog_signal_eqn, sample_rate: 0.001, size: 1000)
8
+
9
+ digital_signal = analog_signal.to_ds
10
+
11
+ fft = digital_signal.fft
12
+
13
+ fft.plot_magnitude(path: './examples/analog_signals/')
14
+
15
+ rate = 0.01
16
+ size = 1000
17
+ fn = ->(x){ Math.sin(x) }
18
+ as64 = Digiproc::AnalogSignal.new(eqn: fn, sample_rate: rate, size: size, quantization_bits: 64, quant_max: 1, quant_min: -1)
19
+ as8 = Digiproc::AnalogSignal.new(eqn: fn, sample_rate: rate, size: size, quantization_bits: 8, quant_max: 1, quant_min: -1)
20
+ as4 = Digiproc::AnalogSignal.new(eqn: fn, sample_rate: rate, size: size, quantization_bits: 4, quant_max: 1, quant_min: -1)
21
+ t = Digiproc::Functions.linspace(0, rate * size, size)
22
+ plt = Digiproc::Rbplot.line(t, as64.digitize, "64 bits")
23
+ plt.add_line(t, as8.digitize, '8 bits')
24
+ plt.add_line(t, as4.digitize, '4 bits')
25
+ plt.path('./examples/analog_signals/')
26
+ plt.title('Quantization Outputs')
27
+ plt.xlabel('time (s)')
28
+ plt.ylabel('magnitude')
29
+ plt.xsteps(10)
30
+ plt.theme(:dark)
31
+ plt.show