Commit e587e7e4 authored by Iris Heisterklaus's avatar Iris Heisterklaus
Browse files

- comments and exercises for Diskrete Faltungs GUI.

parent e31db982
......@@ -41,16 +41,22 @@
"metadata": {},
"source": [
"## Einleitung\n",
"Im Folgenden wird die Faltung\n",
"$g(n)=s(n)\\ast h(n)$\n",
"betrachtet.\n",
"Ein diskretes Signal ist ein Signal, welches nur für ganzzahlige Werte $n$ einen Wert annimmt und sonst Null ist. Auch für die Elementarsignale existieren jeweils zeitdiskrete Versionen. Diese Demonstration nutzt einige davon. \n",
"\n",
"Diskrete Signale können genau wie kontinuierliche Signale gefaltet werden. \n",
"Im Folgenden wird die diskrete Faltung\n",
"$$g(n)=s(n)\\ast h(n)=\\sum_{m=-\\infty}^{\\infty}s(m)h(n-m)$$\n",
"betrachtet und veranschaulicht.\n",
"\n",
"## Demo\n",
"$s(n)$ und $h(n)$ können gewählt werden als:\n",
"* $\\delta(n)$\n",
"* $\\epsilon(n)$\n",
"* $\\epsilon(n)\\cdot\\mathrm{b}^{n}$\n",
"* $rect(n) = \\epsilon(n+M)-\\epsilon(n-M-1)$"
"In der Demonstration stehen verschiedene Signale für $s(n)$ und $h(n)$ zur Verfügung. \n",
"$s(n)$ und $h(n)$ können gewählt werden als zeitdiskrete Varianten von:\n",
"* Dirac-Impuls $\\delta(n)$\n",
"* Sprungfunktion $\\epsilon(n)$\n",
"* Exponentialimpuls $\\epsilon(n)\\cdot\\mathrm{b}^{n}$\n",
"* Rechteckfunktion $rect(n) = \\epsilon(n+M)-\\epsilon(n-M-1)$\n",
"\n",
"Unter der folgenden Abbildungen können diese Funktionen ausgewählt werden und, falls gewünscht, eine Verschiebung um $n_0$ eingestellt werden. Für den Exponentialimpuls ist ebenfalls der Faktor $b$ variierbar, für die Rechteckfunktion ist die Breite $M$ wählbar. In der Abbildung können dann die gewählten Funktionen mit ihren Parametern betrachtet werden."
]
},
{
......@@ -156,7 +162,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Faltung $g(n)=s(n)\\ast h(n)$ wird im Folgenden dargestellt:"
"Anschließend kann hier die Faltung $g(n)=s(n)\\ast h(n)$ der zuvor eingestellten Funktionen betrachtet werden.\n",
"\n",
"Über den Schieberegler kann der Wert für $n$ verändert werden und die Funktion $h(n-m)$ bewegt sich in der oberen Grafik. In der unteren Grafik ist das resultierende Ausgangssignal $g(n)$ zu sehen."
]
},
{
......@@ -213,6 +221,20 @@
" ient_grid(ax); ient_axis(ax);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Aufgaben\n",
"Wähle zunächst für $s(n)$ den Dirac-Impuls und für $h(n)$ verschiedene Funktionen aus. \n",
"* Beobachte das Faltungsergebnis. Ab welchem $n$ ist ein Ergebnis zu sehen? Was passiert, wenn du eine der Funktionen verschiebst?\n",
"* Wie sieht das Ergebnis für zwei Rechteckfunktionen aus? Wie für zwei Sprungfunktionen?\n",
"Wähle nun zwei Rechteckfunktionen mit $M>2$. \n",
"* Bewege den Schieberegler langsam von links nach rechts. An welcher Stelle tritt der erste Wert des Faltungsergebnisses auf? Wie hoch ist dieser Wert?\n",
"* Bewege den Schieberegler eins weiter nach rechts. Nun überlagern sich die beiden Signalen an zwei Positionen. Wie hoch ist der Wert des Faltungsergebnisses nun?\n",
"* Bewege den Schieberegler weiter, bis die beiden Funktionen sich vollständig überlagern. Was passiert, wenn nun der Schieberegler weiter nach rechts geschoben wird? Wie hoch ist der Wert des Faltungsergebnisses? Wie berechnen sich die Höhen des Faltungsergebnisses?"
]
},
{
"cell_type": "markdown",
"metadata": {},
......
%% Cell type:code id: tags:
``` python
# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget
import ipywidgets as widgets
from ipywidgets import interact, interactive, fixed, Layout, HBox, VBox
from IPython.display import clear_output, display, HTML
from scipy import signal # convolution
from ient_nb.ient_plots import *
from ient_nb.ient_signals import *
```
%% Cell type:markdown id: tags:
<div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Demonstrator Diskrete Faltung
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:markdown id: tags:
## Einleitung
Im Folgenden wird die Faltung
$g(n)=s(n)\ast h(n)$
betrachtet.
Ein diskretes Signal ist ein Signal, welches nur für ganzzahlige Werte $n$ einen Wert annimmt und sonst Null ist. Auch für die Elementarsignale existieren jeweils zeitdiskrete Versionen. Diese Demonstration nutzt einige davon.
Diskrete Signale können genau wie kontinuierliche Signale gefaltet werden.
Im Folgenden wird die diskrete Faltung
$$g(n)=s(n)\ast h(n)=\sum_{m=-\infty}^{\infty}s(m)h(n-m)$$
betrachtet und veranschaulicht.
## Demo
$s(n)$ und $h(n)$ können gewählt werden als:
* $\delta(n)$
* $\epsilon(n)$
* $\epsilon(n)\cdot\mathrm{b}^{n}$
* $rect(n) = \epsilon(n+M)-\epsilon(n-M-1)$
In der Demonstration stehen verschiedene Signale für $s(n)$ und $h(n)$ zur Verfügung.
$s(n)$ und $h(n)$ können gewählt werden als zeitdiskrete Varianten von:
* Dirac-Impuls $\delta(n)$
* Sprungfunktion $\epsilon(n)$
* Exponentialimpuls $\epsilon(n)\cdot\mathrm{b}^{n}$
* Rechteckfunktion $rect(n) = \epsilon(n+M)-\epsilon(n-M-1)$
Unter der folgenden Abbildungen können diese Funktionen ausgewählt werden und, falls gewünscht, eine Verschiebung um $n_0$ eingestellt werden. Für den Exponentialimpuls ist ebenfalls der Faktor $b$ variierbar, für die Rechteckfunktion ist die Breite $M$ wählbar. In der Abbildung können dann die gewählten Funktionen mit ihren Parametern betrachtet werden.
%% Cell type:code id: tags:
``` python
n = np.linspace(-10, 10, 21)
m = np.linspace(-40, 40, 81) # m Achse
s_type = h_type = ''; s_n0 = h_n0 = 0
M = 1
b = .5
n0 = -2
def convolution(s, h):
# Convolve s and h numerically
return signal.convolve(s(m), h(m), mode='same')
signal_types = {'Dirac-Impuls' : lambda n: np.where(n==0, 1, 0),
'Sprungfunktion' : unitstep,
'Exponentialimpuls' : lambda n: unitstep(n)*b**n,
'Rechteck' : lambda n: unitstep(n+M) - unitstep(n-M-1)
}
def _update_b(_b):
global b
b = _b
update_signals(s_type, s_n0, h_type, h_n0)
def _update_M(_M):
global M
M = _M
update_signals(s_type, s_n0, h_type, h_n0)
# widgets for setting parameters b and M
w_b = interactive(_update_b, _b=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b$', style=ient_wdgtl_style))
w_M = interactive(_update_M, _M=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M$', style=ient_wdgtl_style))
box = HBox([])
fig0, axs0 = plt.subplots(1, 2, figsize=(8,2)); container_s = container_h = None
@widgets.interact(_s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(n)$:'),
_s_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=ient_wdgtl_style),
_h_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $h(n)$:'),
_h_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=ient_wdgtl_style))
def update_signals(_s_type, _s_n0, _h_type, _h_n0):
# set global variables
global s_type, s_n0, h_type, h_n0
s_type = _s_type; s_n0 = _s_n0; h_type = _h_type; h_n0 = _h_n0
global s, h, gn, container_s, container_h # reused in second interactive plot
s = lambda m: signal_types[_s_type]((m-_s_n0)); # s(m-n0)
h = lambda m: signal_types[_h_type]((m-_h_n0)); # h(m-n0)
gn = convolution(s, h) # numerical convolution
# update second plot if existing
try:
global n0
update_plot(n0)
except NameError:
pass
# show widgets according to chosen s and h
if _s_type == 'Exponentialimpuls' and _h_type == 'Rechteck':
box.children = [w_b, w_M]
elif _s_type == 'Rechteck' and _h_type == 'Exponentialimpuls':
box.children = [w_M, w_b]
elif _s_type == 'Exponentialimpuls' or _h_type == 'Exponentialimpuls':
box.children = [w_b]
elif _s_type == 'Rechteck' or _h_type == 'Rechteck':
box.children = [w_M]
else:
box.children = []
# display s and h plots
if container_s is None:
ax = axs0[0];
container_s = ient_stem(ax, m, s(m), 'rwth')
ax.set_xticks(np.arange(-10, 11, step=2))
ax.set_xlabel(r'$\rightarrow n$'); ax.set_ylabel(r'$\uparrow s(n)$')
ax.set_xlim([-10.9, 10.9]); ax.set_ylim([-1.19, 1.19]); ient_axis(ax); ient_grid(ax);
ax = axs0[1];
container_h = ient_stem(ax, m, h(m), 'rwth')
ax.set_xticks(np.arange(-10, 11, step=2))
ax.set_xlabel(r'$\rightarrow n$'); ax.set_ylabel(r'$\uparrow h(n)$')
ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); ient_axis(ax); ient_grid(ax);
else:
ient_stem_set_ydata(container_s, s(m))
ient_stem_set_ydata(container_h, h(m))
display(box)
```
%% Cell type:markdown id: tags:
Die Faltung $g(n)=s(n)\ast h(n)$ wird im Folgenden dargestellt:
Anschließend kann hier die Faltung $g(n)=s(n)\ast h(n)$ der zuvor eingestellten Funktionen betrachtet werden.
Über den Schieberegler kann der Wert für $n$ verändert werden und die Funktion $h(n-m)$ bewegt sich in der oberen Grafik. In der unteren Grafik ist das resultierende Ausgangssignal $g(n)$ zu sehen.
%% Cell type:code id: tags:
``` python
fig, axs = plt.subplots(2, 1, figsize=(8,6),) # gridspec_kw = {'width_ratios':[3, 1]}
global n0
container_ss = container_hh = container_gg = None
@widgets.interact(n=widgets.FloatSlider(min=-10, max=10, value=n0, step=1, description='Verschiebung $n$', style=ient_wdgtl_style))
def update_plot(n):
global container_ss, container_hh, container_gg
global n0
n0 = n
n_ind = np.where(m>=n); n_ind = n_ind[0][0]; g_plot = gn.copy(); g_plot[n_ind+1:] = 0; # hide g(n') with n'>n
if container_gg is None:
ax = axs[1]
container_gg = ient_stem(ax, m, g_plot)
if container_ss is not None:
ient_stem_set_ydata(container_ss, s(m))
ient_stem_set_ydata(container_hh, h(n-m))
ient_stem_set_ydata(container_gg, g_plot)
ax = axs[0]
ax.texts[0].set_x(n); ax.lines[3].set_xdata([n,n]) # update labels
ax = axs[1]
ient_update_ylim(ax, gn, 0.19, 20);
else:
ax = axs[0];
container_ss = ient_stem(ax, m, s(m), 'grun', label=r'$s(m)$')
container_ss[0].set_markerfacecolor('none');
container_ss[0].set_markersize(8);
container_ss[0].set_markeredgewidth(2);
container_hh = ient_stem(ax, m, h(n-m), 'rwth', label=r'$h(n-m)$')
ient_annotate_xtick(ax, r'$n$', n, -0.1, 'rwth', 15); # mark n on m axis
ax.set_xlabel(r'$\rightarrow m$');
ax.set_xlim([-10.2,10.2]); ient_update_ylim(ax, np.concatenate((h(m), s(m))), 0.19, 5);
ax.set_xticks(np.arange(-10, 11, step=2))
ax.legend(); ient_grid(ax); ient_axis(ax);
ax = axs[1]
ax.set_xlabel(r'$\rightarrow n$'); ax.set_ylabel(r'$\uparrow g(n)=s(n)\ast h(n)$');
ax.set_xlim(axs[0].get_xlim()); ient_update_ylim(ax, gn, 0.19, 20);
ax.set_xticks(np.arange(-10, 11, step=2))
ient_grid(ax); ient_axis(ax);
```
%% Cell type:markdown id: tags:
## Aufgaben
Wähle zunächst für $s(n)$ den Dirac-Impuls und für $h(n)$ verschiedene Funktionen aus.
* Beobachte das Faltungsergebnis. Ab welchem $n$ ist ein Ergebnis zu sehen? Was passiert, wenn du eine der Funktionen verschiebst?
* Wie sieht das Ergebnis für zwei Rechteckfunktionen aus? Wie für zwei Sprungfunktionen?
Wähle nun zwei Rechteckfunktionen mit $M>2$.
* Bewege den Schieberegler langsam von links nach rechts. An welcher Stelle tritt der erste Wert des Faltungsergebnisses auf? Wie hoch ist dieser Wert?
* Bewege den Schieberegler eins weiter nach rechts. Nun überlagern sich die beiden Signalen an zwei Positionen. Wie hoch ist der Wert des Faltungsergebnisses nun?
* Bewege den Schieberegler weiter, bis die beiden Funktionen sich vollständig überlagern. Was passiert, wenn nun der Schieberegler weiter nach rechts geschoben wird? Wie hoch ist der Wert des Faltungsergebnisses? Wie berechnen sich die Höhen des Faltungsergebnisses?
%% Cell type:markdown id: tags:
This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT).
Please attribute the work as follows:
*Christian Rohlfing, Emin Kosar, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2019, Institut für Nachrichtentechnik, RWTH Aachen University.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment