digiproc 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
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
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -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
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 ϴ(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,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
|
Binary file
|