Skip to content
Snippets Groups Projects
Commit 380f501d authored by Oscar Gustafsson's avatar Oscar Gustafsson :bicyclist:
Browse files

Add examples to documentation

parent 1da96dd5
No related branches found
No related tags found
1 merge request!155Add examples to documentation
Pipeline #88764 passed
...@@ -53,6 +53,8 @@ To generate the documentation, the following additional packages are required: ...@@ -53,6 +53,8 @@ To generate the documentation, the following additional packages are required:
- [Sphinx](https://www.sphinx-doc.org/) - [Sphinx](https://www.sphinx-doc.org/)
- [Furo](https://pradyunsg.me/furo/) - [Furo](https://pradyunsg.me/furo/)
- [numpydoc](https://numpydoc.readthedocs.io/) - [numpydoc](https://numpydoc.readthedocs.io/)
- [Sphinx-Gallery](https://sphinx-gallery.github.io/)
- [SciPy](https://scipy.org/)
### Using CMake directly ### Using CMake directly
......
...@@ -22,7 +22,8 @@ extensions = [ ...@@ -22,7 +22,8 @@ extensions = [
'sphinx.ext.autosummary', 'sphinx.ext.autosummary',
'sphinx.ext.inheritance_diagram', 'sphinx.ext.inheritance_diagram',
'sphinx.ext.intersphinx', 'sphinx.ext.intersphinx',
'numpydoc', 'sphinx_gallery.gen_gallery',
'numpydoc', # Needs to be loaded *after* autodoc.
] ]
templates_path = ['_templates'] templates_path = ['_templates']
...@@ -50,3 +51,13 @@ graphviz_dot = shutil.which('dot') ...@@ -50,3 +51,13 @@ graphviz_dot = shutil.which('dot')
html_theme = 'furo' html_theme = 'furo'
html_static_path = ['_static'] html_static_path = ['_static']
# -- Options for sphinx-gallery --
sphinx_gallery_conf = {
'examples_dirs': '../examples', # path to your example scripts
'gallery_dirs': 'examples', # path to where to save gallery generated output
'plot_gallery': 'True', # sphinx-gallery/913
'filename_pattern': '.',
'doc_module': ('b_asic',),
'reference_url': {'b_asic': None},
}
...@@ -22,9 +22,10 @@ Indices and tables ...@@ -22,9 +22,10 @@ Indices and tables
Table of Contents Table of Contents
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 1
self self
api/index api/index
GUI GUI
scheduler_gui scheduler_gui
examples/index
.. _examples:
===============
B-ASIC Examples
===============
These are examples of how B-ASIC can be used.
"""
======================================
First-order IIR Filter with Simulation
======================================
In this example, a direct form first-order IIR filter is designed.
First, we need to import the operations that will be used in the example:
"""
from b_asic.core_operations import Addition, ConstantMultiplication
from b_asic.special_operations import Delay, Input, Output
# %%
# Then, we continue by defining the input and delay element, which we can optionally name.
input = Input(name="My input")
delay = Delay(name="The only delay")
# %%
# There are a few ways to connect signals. Either explicitly, by instantiating them:
a1 = ConstantMultiplication(0.5, delay)
# %%
# By operator overloading:
first_addition = a1 + input
# %%
# Or by creating them, but connecting the input later. Each operation has a function :func:`~b_asic.operation.Operation.input`
# that is used to access a specific input (or output, by using :func:`~b_asic.operation.Operation.output`).
b1 = ConstantMultiplication(0.7)
b1.input(0).connect(delay)
# %%
# The latter is useful when there is not a single order to create the signal flow graph, e.g., for recursive algorithms.
# In this example, we could not connect the output of the delay as that was not yet available.
#
# There is also a shorthand form to connect signals using the ``<<`` operator:
delay << first_addition
# %%
# Naturally, it is also possible to write expressions when instantiating operations:
output = Output(b1 + first_addition)
# %%
# Now, we should create a signal flow graph, but first it must be imported (normally, this should go at the top of the file).
from b_asic.signal_flow_graph import SFG
# %%
# The signal flow graph is defined by its inputs and outputs, so these must be provided. As, in general, there can be
# multiple inputs and outputs, there should be provided as a list or a tuple.
firstorderiir = SFG([input], [output])
# %%
# If this is executed in an enriched terminal, such as a Jupyter Notebook, Jupyter QtConsole, or Spyder, just typing
# the variable name will return a graphical representation of the signal flow graph.
firstorderiir
# %%
# For now, we can print the precendence relations of the SFG
firstorderiir.print_precedence_graph()
# %%
# As seen, each operation has an id, in addition to the optional name. This can be used to access the operation.
# For example,
firstorderiir.find_by_id('cmul1')
# %%
# Note that this operation differs from ``a1`` defined above as the operations are copied and recreated once inserted
# into a signal flow graph.
#
# The signal flow graph can also be simulated. For this, we must import :class:`.Simulation`.
from b_asic.simulation import Simulation
# %%
# The :class:`.Simulation` class require that we provide inputs. These can either be arrays of values or we can use functions
# that provides the values when provided a time index.
#
# Let us create a simulation that simulates a short impulse response:
sim = Simulation(firstorderiir, [[1, 0, 0, 0, 0]])
# %%
# To run the simulation for all input samples, we do:
sim.run()
# %%
# The returned value is the output after the final iteration. However, we may often be interested in the results from
# the whole simulation.
# The results from the simulation, which is a dictionary of all the nodes in the signal flow graph,
# can be obtained as
sim.results
# %%
# Hence, we can obtain the results that we are interested in and, for example, plot the output and the value after the
# first addition:
import matplotlib.pyplot as plt
plt.plot(sim.results['0'], label="Output")
plt.plot(sim.results['add1'], label="After first addition")
plt.legend()
plt.show()
# %%
# To compute and plot the frequency response, it is possible to use SciPy and NumPy as
import numpy as np
import scipy.signal
w, h = scipy.signal.freqz(sim.results['0'])
plt.plot(w, 20 * np.log10(np.abs(h)))
plt.show()
# %%
# As seen, the output has not converged to zero, leading to that the frequency-response may not be correct, so we want
# to simulate for a longer time.
# Instead of just adding zeros to the input array, we can use a function that generates the impulse response instead.
# There are a number of those defined in B-ASIC for convenience, and the one for an impulse response is called :class:`.Impulse`.
from b_asic.signal_generator import Impulse
sim = Simulation(firstorderiir, [Impulse()])
# %%
# Now, as the functions will not have an end, we must run the simulation for a given number of cycles, say 30.
# This is done using :func:`~b_asic.simulation.Simulation.run_for` instead:
sim.run_for(30)
# %%
# Now, plotting the impulse results gives:
plt.plot(sim.results['0'])
plt.show()
# %%
# And the frequency-response:
w, h = scipy.signal.freqz(sim.results['0'])
plt.plot(w, 20 * np.log10(np.abs(h)))
plt.show()
"""A sfg with delays and interesting layout for precedence list generation. """
. . =====================================
IN1>--->C0>--->ADD1>----------+--->A0>--->ADD4>--->OUT1 Second-order IIR Filter with Schedule
. ^ | ^ . =====================================
. | T1 | .
. | | | .
. ADD2<---<B1<---+--->A1>--->ADD3 .
. ^ | ^ .
. | T2 | .
. | | | .
. +-----<B2<---+--->A2>-----+ .
""" """
from b_asic.core_operations import Addition, ConstantMultiplication from b_asic.core_operations import Addition, ConstantMultiplication
...@@ -37,10 +31,15 @@ sfg = SFG( ...@@ -37,10 +31,15 @@ sfg = SFG(
inputs=[in1], outputs=[out1], name="Second-order direct form IIR filter" inputs=[in1], outputs=[out1], name="Second-order direct form IIR filter"
) )
# Set latencies and exection times # %%
# Set latencies and execution times
sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2)
sfg.set_latency_of_type(Addition.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 1)
sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1)
sfg.set_execution_time_of_type(Addition.type_name(), 1) sfg.set_execution_time_of_type(Addition.type_name(), 1)
# %%
# Create schedule
schedule = Schedule(sfg, cyclic=True) schedule = Schedule(sfg, cyclic=True)
schedule.plot_schedule()
""" """
=============================
Third-order Bireciprocal LWDF
=============================
Small bireciprocal lattice wave digital filter. Small bireciprocal lattice wave digital filter.
""" """
from b_asic.core_operations import Addition, SymmetricTwoportAdaptor from b_asic.core_operations import Addition, SymmetricTwoportAdaptor
......
"""Three-point Winograd DFT. """
========================
Three-point Winograd DFT
========================
""" """
from math import cos, pi, sin from math import cos, pi, sin
...@@ -38,7 +41,8 @@ sfg = SFG( ...@@ -38,7 +41,8 @@ sfg = SFG(
name="3-point Winograd DFT", name="3-point Winograd DFT",
) )
# Set latencies and exection times # %%
# Set latencies and execution times
sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2) sfg.set_latency_of_type(ConstantMultiplication.type_name(), 2)
sfg.set_latency_of_type(Addition.type_name(), 1) sfg.set_latency_of_type(Addition.type_name(), 1)
sfg.set_latency_of_type(Subtraction.type_name(), 1) sfg.set_latency_of_type(Subtraction.type_name(), 1)
...@@ -46,4 +50,7 @@ sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1) ...@@ -46,4 +50,7 @@ sfg.set_execution_time_of_type(ConstantMultiplication.type_name(), 1)
sfg.set_execution_time_of_type(Addition.type_name(), 1) sfg.set_execution_time_of_type(Addition.type_name(), 1)
sfg.set_execution_time_of_type(Subtraction.type_name(), 1) sfg.set_execution_time_of_type(Subtraction.type_name(), 1)
# %%
# Generate schedule
schedule = Schedule(sfg, cyclic=True) schedule = Schedule(sfg, cyclic=True)
schedule.plot_schedule()
""" """
B-ASIC automatically generated SFG file. ==================
Name: twotapfir Two-tap FIR filter
Last saved: 2023-01-24 14:38:17.654639. ==================
""" """
from b_asic import ( from b_asic import (
SFG, SFG,
......
sphinx sphinx
furo furo
numpydoc numpydoc
sphinx-gallery
scipy
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment