Commit 44c4bb33 authored by Hafiz Emin Kosar's avatar Hafiz Emin Kosar
Browse files

- adapted notebooks to rwth_nb

parent 27d4c135
......@@ -13,16 +13,17 @@
"source": [
"# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University\n",
"%matplotlib widget\n",
"\n",
"import ipywidgets as widgets\n",
"from ipywidgets import interact, interactive\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import scipy as sp\n",
"import scipy.special\n",
"import scipy.signal\n",
"\n",
"from ient_nb.ient_plots import *\n",
"from ient_nb.ient_signals import *"
"import rwth_nb.plots.mpl_decorations as rwth_plots\n",
"from rwth_nb.misc.signals import *"
]
},
{
......@@ -30,7 +31,7 @@
"metadata": {},
"source": [
"<div>\n",
" <img src=\"ient_nb/figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
" <img src=\"figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
"</div>\n",
"\n",
"# Auto- und Kreuzkorrelationsfunktion von Energiesignalen\n",
......@@ -145,11 +146,11 @@
"source": [
"fig0, axs0 = plt.subplots(1, 2, figsize=(8,2))\n",
"@widgets.interact(s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(t)$:'),\n",
" s_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=ient_wdgtl_style), \n",
" s_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=ient_wdgtl_style), \n",
" s_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=rwth_plots.wdgtl_style), \n",
" s_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=rwth_plots.wdgtl_style), \n",
" g_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $g(t)$:'),\n",
" g_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=ient_wdgtl_style), \n",
" g_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=ient_wdgtl_style))\n",
" g_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=rwth_plots.wdgtl_style), \n",
" g_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=rwth_plots.wdgtl_style))\n",
"def update_signals(s_type, s_T, s_t0, g_type, g_T, g_t0):\n",
" global s, g, phi_sg # reused in second interactive plot\n",
" s = lambda t: signal_types[s_type]((t-s_t0)/s_T);\n",
......@@ -157,23 +158,23 @@
" phi_sg = correlation(s, g) # numerical correlation\n",
" \n",
" if not axs0[0].lines: # plot s(t) and g(t)\n",
" ax = axs0[0]; ax.plot(t, s(t), 'rwth');\n",
" ax = axs0[0]; ax.plot(t, s(t), 'rwth:blue');\n",
" ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow s(t)$')\n",
" ax.set_xlim([-2.9, 2.9]); ax.set_ylim([-1.19, 1.19]); ient_axis(ax); ient_grid(ax);\n",
" ax.set_xlim([-2.9, 2.9]); ax.set_ylim([-1.19, 1.19]); rwth_plots.axis(ax); rwth_plots.grid(ax);\n",
" \n",
" ax = axs0[1]; ax.plot(t, g(t), 'rwth');\n",
" ax = axs0[1]; ax.plot(t, g(t), 'rwth:blue');\n",
" ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow g(t)$')\n",
" ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); ient_axis(ax); ient_grid(ax);\n",
" ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); rwth_plots.axis(ax); rwth_plots.grid(ax);\n",
" else: # update lines\n",
" axs0[0].lines[0].set_ydata(s(t)); \n",
" axs0[1].lines[0].set_ydata(g(t));\n",
" try: # if convolution figure is already opened, update s(t)\n",
" if axs[0].lines:\n",
" axs[0].lines[0].set_ydata((g(t)));\n",
" ient_update_ylim(axs[0], np.concatenate((g(t), s(t))), 0.19, 5); ient_update_ylim(axs[1], phi_sg, 0.19, 5);\n",
" rwth_plots.update_ylim(axs[0], np.concatenate((g(t), s(t))), 0.19, 5); rwth_plots.update_ylim(axs[1], phi_sg, 0.19, 5);\n",
" update_plot(-2); # update correlation plot\n",
" except: pass\n",
" ient_update_ylim(axs0[0], s(t), 0.19, 5); ient_update_ylim(axs0[1], g(t), 0.19, 5); "
" rwth_plots.update_ylim(axs0[0], s(t), 0.19, 5); rwth_plots.update_ylim(axs0[1], g(t), 0.19, 5); "
]
},
{
......@@ -194,35 +195,35 @@
},
"outputs": [],
"source": [
"fig, axs=plt.subplots(2, 1, figsize=(8,6),) # gridspec_kw = {'width_ratios':[3, 1]}\n",
"@widgets.interact(tau_shft=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description=r'Verschiebung $\\tau$', style=ient_wdgtl_style), \n",
" show_integrand=widgets.Checkbox(value=True, description='Zeige Integrand', style=ient_wdgtl_style))\n",
"fig, axs=plt.subplots(2, 1, figsize=(8, 8 / rwth_plots.fig_aspect))\n",
"@widgets.interact(tau_shft=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description=r'Verschiebung $\\tau$', style=rwth_plots.wdgtl_style), \n",
" show_integrand=widgets.Checkbox(value=True, description='Zeige Integrand', style=rwth_plots.wdgtl_style))\n",
"def update_plot(tau_shft, show_integrand=True):\n",
" tau_ind = np.where(tau>=tau_shft); tau_ind = tau_ind[0][0]; phi_plot = phi_sg.copy(); phi_plot[tau_ind:] = np.nan; # hide g(t') with t'>t\n",
" sg = np.conj(s(t-tau_shft))*g(t) # integrand\n",
" \n",
" if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time\n",
" ax = axs[0]; ax.plot(t, g(t), 'rwth', label=r'$g(t)$'); # plot g(t)\n",
" ax.plot(t, np.conj(s(t-tau_shft)), 'grun', label=r'$s^\\ast(t-\\tau)$'); # plot s(t-tau)\n",
" ax.plot(t, sg, '--', color='orange', lw=1, label=r'$g(t)s^\\ast(t-\\tau)$'); # plot integrand\n",
" ient_annotate_xtick(ax, r'$\\tau$', tau_shft, -0.1, 'rwth', 15); # mark t on tau axis\n",
" ax.fill_between(t, 0, sg, facecolor=\"none\", hatch=\"//\", edgecolor='k', linewidth=0.0); # hatch common area\n",
" ax = axs[0]; ax.plot(t, g(t), 'rwth:blue', label=r'$g(t)$'); # plot g(t)\n",
" ax.plot(t, np.conj(s(t-tau_shft)), 'rwth:green', label=r'$s^\\ast(t-\\tau)$'); # plot s(t-tau)\n",
" ax.plot(t, sg, '--', color='rwth:orange', lw=1, label=r'$g(t)s^\\ast(t-\\tau)$'); # plot integrand\n",
" rwth_plots.annotate_xtick(ax, r'$\\tau$', tau_shft, -0.1, 'rwth:blue', 15); # mark t on tau axis\n",
" ax.fill_between(t, 0, sg, facecolor=\"none\", hatch=\"//\", edgecolor='rwth:black', linewidth=0.0); # hatch common area\n",
" ax.set_xlabel(r'$\\rightarrow t$');\n",
" ax.set_xlim([-4.2,4.2]); ient_update_ylim(ax, np.concatenate((g(t), s(t))), 0.19, 5);\n",
" ax.legend(); ient_grid(ax); ient_axis(ax);\n",
" ax.set_xlim([-4.2,4.2]); rwth_plots.update_ylim(ax, np.concatenate((g(t), s(t))), 0.19, 5);\n",
" ax.legend(); rwth_plots.axis(ax); rwth_plots.grid(ax); \n",
" \n",
" ax = axs[1]; ax.plot(tau, phi_plot); # plot phi_sg(tau)\n",
" ax.plot([tau_shft, tau_shft], [0, phi_sg[tau_ind]], 'ko--', lw=1);\n",
" ax.set_xlabel(r'$\\rightarrow \\tau$'); \n",
" ax.set_ylabel(r'$\\uparrow \\varphi_{sg}^\\mathrm{E}(\\tau) = \\int g(t) s^\\ast(t-\\tau)\\mathrm{d}t$'); \n",
" ax.set_xlim(axs[0].get_xlim()); ient_update_ylim(ax, phi_sg, 0.19, 5); \n",
" ient_axis(ax); ient_grid(ax); fig.tight_layout(); \n",
" ax.set_xlim(axs[0].get_xlim()); rwth_plots.update_ylim(ax, phi_sg, 0.19, 5); \n",
" rwth_plots.axis(ax); rwth_plots.grid(ax); fig.tight_layout(); \n",
" \n",
" else: # Replace only xdata and ydata since plt.plot() takes longer time\n",
" ax = axs[0]; ax.lines[1].set_ydata(np.conj(s(t-tau_shft))); ax.lines[2].set_ydata(sg); # update signals\n",
" ax.texts[0].set_x(tau_shft); ax.lines[3].set_xdata([tau_shft,tau_shft]) # update labels\n",
" if ax.collections: ax.collections[0].remove(); # update integrand\n",
" if show_integrand: ax.fill_between(t,0,sg, facecolor=\"none\", hatch=\"//\", edgecolor='k', linewidth=0.0);\n",
" if show_integrand: ax.fill_between(t,0,sg, facecolor=\"none\", hatch=\"//\", edgecolor='rwth:black', linewidth=0.0);\n",
" ax = axs[1]; ax.lines[0].set_ydata(phi_plot); # update signals\n",
" ax.lines[1].set_xdata([tau_shft, tau_shft]); ax.lines[1].set_ydata([0, phi_sg[tau_ind]]); # update labels\n",
"\n",
......
%% Cell type:code id: tags:
``` python
# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget
import ipywidgets as widgets
from ipywidgets import interact, interactive
import numpy as np
import matplotlib.pyplot as plt
import scipy as sp
import scipy.special
import scipy.signal
from ient_nb.ient_plots import *
from ient_nb.ient_signals import *
import rwth_nb.plots.mpl_decorations as rwth_plots
from rwth_nb.misc.signals import *
```
%% Cell type:markdown id: tags:
<div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Auto- und Kreuzkorrelationsfunktion von Energiesignalen
## Einleitung
### Energiesignal
Ein Signal $s(t)$ heißt Energiesignal, wenn seine Signalenergie endlich ist, es gilt also
$$E_s = \int\limits_{-\infty}^\infty |s(t)|^2 \mathrm{d} t < \infty \text{ .}$$
Viele wichtige Signale haben keine endliche Gesamtenergie, z. B. alle periodischen Signale, die Sprungfunktion oder zeitlich nicht begrenzte Zufallssignale. Für Signale mit Dirac-Impulsen ist die Energie nicht definiert.
### Kreuzkorrelationsfunktion
Für zwei Energiesignale $s(t)$ und $g(t)$ kann die *Kreuzkorrelationsfunktion* berechnet werden. Diese zeigt an, wie ähnlich sich zwei Signale bei unterschiedlichen Verschiebungen $\tau$ sind.
$$
\varphi_{sg}^\mathrm{E}(\tau)
= \int\limits_{-\infty}^\infty s^\ast(t) g(t+\tau)\mathrm{d}t
\stackrel{t\rightarrow -t}{=} \int\limits_{-\infty}^\infty s(-t)^\ast g(\tau-t) \mathrm{d} t
= s^\ast(-\tau) \ast g(\tau)
= \left[\varphi_{gs}^\mathrm{E}(-\tau)\right]^\ast
$$
Die Kreuzkorrelationsfunktionen $\varphi_{sg}^\mathrm{E}(\tau)$ und $\varphi_{gs}^\mathrm{E}(\tau)$ sind also zueinander zeitgespiegelt und konjugiert-komplex.
Für die Berechnung der Kreuzkorrelationsfunktion müssen die beiden Signale nicht zwingend Energiesignale sein, es ist ausreichend, dass das Integral berechnet werden kann. Man beachte hier auch die Ähnlichkeit zur Faltung zweier Signale, bei der Berechnung kann entsprechend vorgegangen werden.
### Autokorrelationsfunktion
Die Autokorrelationsfunktion entspricht der Kreuzkorrelationsfunktion, wenn $g(t) = s(t)$ gilt. Sie zeigt an, wie ähnlich ein Signal sich selber bei einer zeitlichen Verschiebung $\tau$ ist
$$
\varphi_{ss}^\mathrm{E}(\tau)
= \int\limits_{-\infty}^\infty s^\ast(t) s(t+\tau)\mathrm{d}t \text{.}
$$
Die Autokorrelationsfunktion besitzt folgende allgemeingültige Eigenschaften:
* Die Autokorrelationsfunktion ist immer eine gerade Funktion.
* Den maximalen Wert nimmt eine Autokorrelationsfunktion für $\tau=0$ an, da in diesem Fall größte Ähnlichkeit vorliegt.
* Das Maximum der Autokorrelationsfunktion eines Energiesignals ist gleich seiner Energie
$$\varphi_{ss}^\mathrm{E}(0)=E_s \text{.}$$
* Bei zeitlich begrenzten Signalen hat die Autokorrelationsfunktion die doppelte Breite des Signals.
%% Cell type:markdown id: tags:
## Interaktive Demo
Die interaktive Demo ermöglicht es, sich die Kreuz- und Autokorrelation für verschiedene Signale anzusehen.
$$
\varphi_{sg}^\mathrm{E}(\tau)
= s^\ast(-\tau) \ast g(\tau)
= g(\tau) \ast s^\ast(-\tau)
= \int\limits_{-\infty}^\infty g(t) s^\ast(t-\tau) \mathrm{d} t
$$
Es ist auch möglich, eine eigene Funktion $s_0(t)$ zu definieren.
%% Cell type:code id: tags:
``` python
s_0 = lambda t: rect(t/2-1/2)*(-t)
```
%% Cell type:code id: tags:
``` python
def correlation(s, g):
# Correlate s and g numerically
return sp.signal.convolve(np.conj(s(-t)),g(t), mode='full')*deltat
fs = 2000 # Samplingrate
(t,deltat) = np.linspace(-8,8, 16*fs, retstep=True) # Zeitachse
(tau,deltatau) = np.linspace(-16,16, 2*len(t)-1, retstep=True) # Korrelation
signal_types = {'Rechteck' : rect,
'Dreieck' : tri,
'Sprungfunktion' : unitstep,
'si-Funktion' : lambda t: si(t*np.pi),
'Exponentialimpuls' : lambda t: unitstep(t)*np.exp(-t),
'Gauß-Signal' : gauss,
'Doppelrechteck' : lambda t: rect(t*2+0.5)-rect(t*2-0.5),
'Rampe' : lambda t: t*rect(t-0.5),
'Versch. Rechteck' : lambda t: -rect(t-0.5),
'Eigene Kreation' : s_0,
}
```
%% Cell type:markdown id: tags:
Wähle Signale für $s(t)$ und $g(t)$ im Drop-Down-Menü aus. Für beide Signale kann auch die Breite $T$ und die Verschiebung $t_0$ angepasst werden. Die jeweiligen Signale werden dann in der nachfolgenden Abbildung angezeigt.
%% Cell type:code id: tags:
``` python
fig0, axs0 = plt.subplots(1, 2, figsize=(8,2))
@widgets.interact(s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(t)$:'),
s_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=ient_wdgtl_style),
s_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=ient_wdgtl_style),
s_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=rwth_plots.wdgtl_style),
s_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=rwth_plots.wdgtl_style),
g_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $g(t)$:'),
g_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=ient_wdgtl_style),
g_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=ient_wdgtl_style))
g_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=rwth_plots.wdgtl_style),
g_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=rwth_plots.wdgtl_style))
def update_signals(s_type, s_T, s_t0, g_type, g_T, g_t0):
global s, g, phi_sg # reused in second interactive plot
s = lambda t: signal_types[s_type]((t-s_t0)/s_T);
g = lambda t: signal_types[g_type]((t-g_t0)/g_T);
phi_sg = correlation(s, g) # numerical correlation
if not axs0[0].lines: # plot s(t) and g(t)
ax = axs0[0]; ax.plot(t, s(t), 'rwth');
ax = axs0[0]; ax.plot(t, s(t), 'rwth:blue');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s(t)$')
ax.set_xlim([-2.9, 2.9]); ax.set_ylim([-1.19, 1.19]); ient_axis(ax); ient_grid(ax);
ax.set_xlim([-2.9, 2.9]); ax.set_ylim([-1.19, 1.19]); rwth_plots.axis(ax); rwth_plots.grid(ax);
ax = axs0[1]; ax.plot(t, g(t), 'rwth');
ax = axs0[1]; ax.plot(t, g(t), 'rwth:blue');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow g(t)$')
ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); ient_axis(ax); ient_grid(ax);
ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); rwth_plots.axis(ax); rwth_plots.grid(ax);
else: # update lines
axs0[0].lines[0].set_ydata(s(t));
axs0[1].lines[0].set_ydata(g(t));
try: # if convolution figure is already opened, update s(t)
if axs[0].lines:
axs[0].lines[0].set_ydata((g(t)));
ient_update_ylim(axs[0], np.concatenate((g(t), s(t))), 0.19, 5); ient_update_ylim(axs[1], phi_sg, 0.19, 5);
rwth_plots.update_ylim(axs[0], np.concatenate((g(t), s(t))), 0.19, 5); rwth_plots.update_ylim(axs[1], phi_sg, 0.19, 5);
update_plot(-2); # update correlation plot
except: pass
ient_update_ylim(axs0[0], s(t), 0.19, 5); ient_update_ylim(axs0[1], g(t), 0.19, 5);
rwth_plots.update_ylim(axs0[0], s(t), 0.19, 5); rwth_plots.update_ylim(axs0[1], g(t), 0.19, 5);
```
%% Cell type:markdown id: tags:
In der nachfolgenden Grafik kann für die beiden oben ausgewählten Funktionen nun das Ergebnis der Kreuzkorrelationsfunktion betrachtet werden. Hierfür muss der Schieberegler von links nach rechts geschoben werden. Wenn das Kästchen bei Integrand angeklickt ist, wird die aktuell überlappende Fläche der beiden Funktionen gestrichelt angezeigt. Diese entspricht dem Wert der Kreuzkorrelationsfunktion. Dies kann im unteren Teil der Grafik interaktiv betrachtet werden.
%% Cell type:code id: tags:
``` python
fig, axs=plt.subplots(2, 1, figsize=(8,6),) # gridspec_kw = {'width_ratios':[3, 1]}
@widgets.interact(tau_shft=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description=r'Verschiebung $\tau$', style=ient_wdgtl_style),
show_integrand=widgets.Checkbox(value=True, description='Zeige Integrand', style=ient_wdgtl_style))
fig, axs=plt.subplots(2, 1, figsize=(8, 8 / rwth_plots.fig_aspect))
@widgets.interact(tau_shft=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description=r'Verschiebung $\tau$', style=rwth_plots.wdgtl_style),
show_integrand=widgets.Checkbox(value=True, description='Zeige Integrand', style=rwth_plots.wdgtl_style))
def update_plot(tau_shft, show_integrand=True):
tau_ind = np.where(tau>=tau_shft); tau_ind = tau_ind[0][0]; phi_plot = phi_sg.copy(); phi_plot[tau_ind:] = np.nan; # hide g(t') with t'>t
sg = np.conj(s(t-tau_shft))*g(t) # integrand
if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time
ax = axs[0]; ax.plot(t, g(t), 'rwth', label=r'$g(t)$'); # plot g(t)
ax.plot(t, np.conj(s(t-tau_shft)), 'grun', label=r'$s^\ast(t-\tau)$'); # plot s(t-tau)
ax.plot(t, sg, '--', color='orange', lw=1, label=r'$g(t)s^\ast(t-\tau)$'); # plot integrand
ient_annotate_xtick(ax, r'$\tau$', tau_shft, -0.1, 'rwth', 15); # mark t on tau axis
ax.fill_between(t, 0, sg, facecolor="none", hatch="//", edgecolor='k', linewidth=0.0); # hatch common area
ax = axs[0]; ax.plot(t, g(t), 'rwth:blue', label=r'$g(t)$'); # plot g(t)
ax.plot(t, np.conj(s(t-tau_shft)), 'rwth:green', label=r'$s^\ast(t-\tau)$'); # plot s(t-tau)
ax.plot(t, sg, '--', color='rwth:orange', lw=1, label=r'$g(t)s^\ast(t-\tau)$'); # plot integrand
rwth_plots.annotate_xtick(ax, r'$\tau$', tau_shft, -0.1, 'rwth:blue', 15); # mark t on tau axis
ax.fill_between(t, 0, sg, facecolor="none", hatch="//", edgecolor='rwth:black', linewidth=0.0); # hatch common area
ax.set_xlabel(r'$\rightarrow t$');
ax.set_xlim([-4.2,4.2]); ient_update_ylim(ax, np.concatenate((g(t), s(t))), 0.19, 5);
ax.legend(); ient_grid(ax); ient_axis(ax);
ax.set_xlim([-4.2,4.2]); rwth_plots.update_ylim(ax, np.concatenate((g(t), s(t))), 0.19, 5);
ax.legend(); rwth_plots.axis(ax); rwth_plots.grid(ax);
ax = axs[1]; ax.plot(tau, phi_plot); # plot phi_sg(tau)
ax.plot([tau_shft, tau_shft], [0, phi_sg[tau_ind]], 'ko--', lw=1);
ax.set_xlabel(r'$\rightarrow \tau$');
ax.set_ylabel(r'$\uparrow \varphi_{sg}^\mathrm{E}(\tau) = \int g(t) s^\ast(t-\tau)\mathrm{d}t$');
ax.set_xlim(axs[0].get_xlim()); ient_update_ylim(ax, phi_sg, 0.19, 5);
ient_axis(ax); ient_grid(ax); fig.tight_layout();
ax.set_xlim(axs[0].get_xlim()); rwth_plots.update_ylim(ax, phi_sg, 0.19, 5);
rwth_plots.axis(ax); rwth_plots.grid(ax); fig.tight_layout();
else: # Replace only xdata and ydata since plt.plot() takes longer time
ax = axs[0]; ax.lines[1].set_ydata(np.conj(s(t-tau_shft))); ax.lines[2].set_ydata(sg); # update signals
ax.texts[0].set_x(tau_shft); ax.lines[3].set_xdata([tau_shft,tau_shft]) # update labels
if ax.collections: ax.collections[0].remove(); # update integrand
if show_integrand: ax.fill_between(t,0,sg, facecolor="none", hatch="//", edgecolor='k', linewidth=0.0);
if show_integrand: ax.fill_between(t,0,sg, facecolor="none", hatch="//", edgecolor='rwth:black', linewidth=0.0);
ax = axs[1]; ax.lines[0].set_ydata(phi_plot); # update signals
ax.lines[1].set_xdata([tau_shft, tau_shft]); ax.lines[1].set_ydata([0, phi_sg[tau_ind]]); # update labels
axs[0].lines[2].set_visible(show_integrand)
```
%% Cell type:markdown id: tags:
## Aufgaben
* Wähle zwei gleiche Funktionen aus. Überprüfe die oben angegebenen Eigenschaften der Autokorrelationsfunktion. Variiere hierbei die Funktionen und betrachte die Autokorrelationsfunktion verschiedener Signale.
* Wie ändert sich das Ergebnis, wenn die Breite eines der beiden Signale sich ändert?
* Wähle zwei verschiedene Signale aus und beobachte, wo in diesen Fällen die maximale Kreuzkorrelation auftritt. Kannst du erklären, warum?
%% 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, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2020, Institut für Nachrichtentechnik, RWTH Aachen University.
......
......@@ -38,7 +38,7 @@
"metadata": {},
"source": [
"<div>\n",
" <img src=\"ient_nb/figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
" <img src=\"figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
"</div>\n",
"\n",
"# Blockdiagramme\n",
......
%% Cell type:code id: tags:
``` python
import sys
sys.path.insert(0,'./ient_nb')
%reload_ext ient_tikzmagic
```
%% Cell type:code id: tags:
``` python
%%html
<style>
.output_wrapper button.btn.btn-default,
.output_wrapper .ui-dialog-titlebar {
display: none;
}
</style>
```
%% Cell type:markdown id: tags:
<div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Blockdiagramme
Einige Blockdiagramme, die in den anderen Notebooks benutzt werden.
%% Cell type:code id: tags:
``` python
%%tikz --size 200,100
\tikzstyle{line} = [draw,black,-latex]
\tikzstyle{sig} = [inner sep=1pt]
\tikzstyle{block} = [draw, fill=white]
\node[block](h){$h(t)$};
\node[sig,left=.5 of h](s){$s(t)$};
\node[sig,right=.5 of h](g){$g(t)$};
\draw[line,shorten >=1pt](s)--(h);
\draw[line,shorten <=1pt](h)--(g);
```
%%%% Output: display_data
[Hidden Image Output]
%% Cell type:code id: tags:
``` python
%%tikz --size 200,100
\tikzstyle{line} = [draw,black,-latex]
\tikzstyle{sig} = [inner sep=1pt]
\tikzstyle{block} = [draw, fill=white]
\node[block](h){$h(t)$};
\node[sig,left=.5 of h](s){${}^k n(t)$};
\node[sig,right=.5 of h](g){${}^k g(t)$};
\draw[line,shorten >=1pt](s)--(h);
\draw[line,shorten <=1pt](h)--(g);
```
%%%% Output: display_data
[Hidden Image Output]
%% Cell type:code id: tags:
``` python
%%tikz --size 400,100
% sampler
\newcommand\sampler[3]{
\begin{scope}[shift={#1}]
\node[branch](#2l){};
\node[branch,right=.5 of #2l](#2r){};
\draw[line,-](#2r.center) -- ($(#2l)!.3!90:(#2r)$);
\node[state,anchor=south](#2) at ($(#2l)!.5!(#2r)+(0,.75)$){#3};
\draw[line,shorten <=2pt](#2.south)-- ++(0,-.5);
\end{scope}
}
\tikzstyle{block} = [rectangle, draw, minimum size=1em, text centered, fill=white,inner sep=3pt]
\tikzstyle{circblock} = [draw, circle, node distance = 5em, minimum size=0.5em,inner sep=0.1em]
\tikzstyle{branch} = [draw,fill,shape=circle,minimum size=0.2em,inner sep=0em,node distance=3em]
\tikzstyle{state} = [text badly centered, node distance=0em, inner sep=0pt, align=left]
\tikzstyle{connector} = [draw,shape=circle,minimum size=0.25em,inner sep=0em, node distance=3em]
\tikzstyle{line} = [draw,-stealth',black]
\sampler{(0,0)}{s1}{$nT$};
\node[state , yshift=-5] at ($(s1l)!.5!(s1r)$){$\delta$};
\node[connector , left=.5 of s1l, label={left:$s(t)$}](in) {};
\node[block , right=1.5 of s1r](H) {$h_{\mathrm{TP}}(t)$};
\node[circblock, right=.5 of H](T){$T$};
\node[connector , right=0.5 of T, label={right:$g(t)$}](out) {};
\draw[line ,-](in) -- (s1l);
\draw[line](s1r) -- (H) node[midway , anchor=south]{$s_\mathrm{a}(t)$};
\draw[line](H) -- (T);
\draw[line ,-](T) -- (out);
```
%%%% Output: display_data
[Hidden Image Output]
%% Cell type:code id: tags:
``` python
%%tikz --size 300,300 --tikzpicture /tikz/circuitikz/bipoles/length=1cm
\draw
(0,0) to [short,o-*] ++(-1,0) to [R,l=$R$,*-o] ++(-2,0)
(0,-2) to [short,o-o] ++ (-3,0)
(-1,0) to [L,l=$L$,*-*] ++(0,-2)
(-3,0) to [open, v^=$u_1(t)$] ++(0,-2)
(0,0) to [open, v^=$u_2(t)$] ++(0,-2)
;
```
%%%% Output: display_data
[Hidden Image Output]
%% Cell type:code id: tags:
``` python
%%tikz --size 300,300 --tikzpicture /tikz/circuitikz/bipoles/length=1cm
\draw
(0,0) to [R,l=$R$,o-] ++(2,0) to [L,l=$L$,-] ++(2,0) coordinate(c_up) to [C,l=$C$,*-*] ++(0,-2) coordinate(c_down)
(0,0) to [open, v^=$u_1(t)$] ++(0,-2) coordinate(u1_down)
(c_up) to [short, -o] ++(1,0) to [open, v^=$u_2(t)$] ($(c_down)+(1,0)$) to [short, o-] ++(-1,0) to [short, -o] (u1_down)
;
```
%%%% Output: display_data
[Hidden Image Output]
%% 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, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2019, Institut für Nachrichtentechnik, RWTH Aachen University.
......
......@@ -12,15 +12,16 @@
"source": [
"# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University\n",
"%matplotlib widget\n",
"\n",
"import ipywidgets as widgets\n",
"from ipywidgets import interact, interactive, fixed, Layout, HBox, VBox\n",
"from IPython.display import clear_output, display, HTML\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from scipy import signal # convolution\n",
"\n",
"from ient_nb.ient_plots import *\n",
"from ient_nb.ient_signals import *"
"import rwth_nb.plots.mpl_decorations as rwth_plots\n",
"from rwth_nb.misc.signals import *"
]
},
{
......@@ -28,7 +29,7 @@
"metadata": {},
"source": [
"<div>\n",
" <img src=\"ient_nb/figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
" <img src=\"figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
"</div>\n",
"\n",
"# Demonstrator Diskrete Faltung\n",
......@@ -98,7 +99,7 @@
" 'Eigene Kreation s0(n)' : lambda n, b, M: s_0(n)\n",
" }\n",
"\n",
"fig0, axs0 = plt.subplots(1, 2, figsize=(ient_fig_width, ient_fig_width/4));\n",
"fig0, axs0 = plt.subplots(1, 2, figsize=(rwth_plots.fig_width, rwth_plots.fig_width/4));\n",
"def update_signals(s_type, s_n0, h_type, h_n0, b_s, b_h, M_s, M_h):\n",
" # show widgets according to chosen s and h\n",
" w_b_s.layout.visibility = 'visible' if s_type == 'Exponentialimpuls' else 'hidden'; w_M_s.layout.visibility = 'visible' if s_type == 'Rechteck' else 'hidden'\n",
......@@ -121,35 +122,35 @@
" if container_s is None:\n",
" # plot s\n",
" ax = axs0[0]; \n",
" container_s = ient_stem(ax, m, s(m), 'rwth')\n",
" container_s = rwth_plots.stem(ax, m, s(m), 'rwth:blue')\n",
" ax.set_xticks(np.arange(-10, 11, step=2))\n",
" ax.set_xlabel(r'$\\rightarrow n$'); ax.set_ylabel(r'$\\uparrow s(n)$')\n",
" ax.set_xlim([-10.9, 10.9]); ient_axis(ax); ient_grid(ax);\n",
" ax.set_xlim([-10.9, 10.9]); rwth_plots.axis(ax); rwth_plots.grid(ax);\n",
" \n",
" # plot h\n",
" ax = axs0[1]; \n",
" container_h = ient_stem(ax, m, h(m), 'rwth')\n",
" container_h = rwth_plots.stem(ax, m, h(m), 'rwth:blue')\n",
" ax.set_xticks(np.arange(-10, 11, step=2))\n",
" ax.set_xlabel(r'$\\rightarrow n$'); ax.set_ylabel(r'$\\uparrow h(n)$')\n",
" ax.set_xlim(axs0[0].get_xlim()); ient_axis(ax); ient_grid(ax);\n",
" ax.set_xlim(axs0[0].get_xlim()); rwth_plots.axis(ax); rwth_plots.grid(ax);\n",
"\n",
" else:\n",
" ient_stem_set_ydata(container_s, s(m))\n",
" ient_stem_set_ydata(container_h, h(m))\n",
" rwth_plots.stem_set_ydata(container_s, s(m))\n",
" rwth_plots.stem_set_ydata(container_h, h(m))\n",
" \n",
" # update limits\n",
" ient_update_ylim(axs0[0], s(m), .19)\n",
" ient_update_ylim(axs0[1], h(m), .19)\n",
" rwth_plots.update_ylim(axs0[0], s(m), .19)\n",
" rwth_plots.update_ylim(axs0[1], h(m), .19)\n",
"\n",
"# Widgets\n",
"w_s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(n)$:', style=ient_wdgtl_style)\n",
"w_s_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=ient_wdgtl_style)\n",
"w_h_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $h(n)$:', style=ient_wdgtl_style)\n",
"w_h_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=ient_wdgtl_style)\n",
"w_b_s=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_s$', style=ient_wdgtl_style)\n",
"w_b_h=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_h$', style=ient_wdgtl_style)\n",
"w_M_s=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_s$', style=ient_wdgtl_style)\n",
"w_M_h=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_h$', style=ient_wdgtl_style)\n",
"w_s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(n)$:', style=rwth_plots.wdgtl_style)\n",
"w_s_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=rwth_plots.wdgtl_style)\n",
"w_h_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $h(n)$:', style=rwth_plots.wdgtl_style)\n",
"w_h_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=rwth_plots.wdgtl_style)\n",
"w_b_s=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_s$', style=rwth_plots.wdgtl_style)\n",
"w_b_h=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_h$', style=rwth_plots.wdgtl_style)\n",
"w_M_s=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_s$', style=rwth_plots.wdgtl_style)\n",
"w_M_h=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_h$', style=rwth_plots.wdgtl_style)\n",
"w = widgets.interactive(update_signals, s_type=w_s_type, s_n0=w_s_n0, h_type=w_h_type, h_n0 =w_h_n0, b_s=w_b_s, b_h=w_b_h, M_s=w_M_s, M_h=w_M_h)\n",
"display(widgets.HBox((widgets.VBox((w_s_type, w_s_n0, w_b_s, w_M_s)), widgets.VBox((w_h_type, w_h_n0, w_b_h, w_M_h), layout=Layout(margin='0 0 0 100px'))))); w.update();\n"
]
......@@ -173,10 +174,10 @@
},
"outputs": [],
"source": [
"fig, axs = plt.subplots(2, 1, **ient_landscape)\n",
"fig, axs = plt.subplots(2, 1, **rwth_plots.landscape)\n",
"global n0\n",
"container_ss = container_hh = container_gg = None\n",
"@widgets.interact(n=widgets.FloatSlider(min=-10, max=10, value=n0, step=1, description='Verschiebung $n$', style=ient_wdgtl_style))\n",
"@widgets.interact(n=widgets.FloatSlider(min=-10, max=10, value=n0, step=1, description='Verschiebung $n$', style=rwth_plots.wdgtl_style))\n",
"def update_plot(n):\n",
" global container_ss, container_hh, container_gg\n",
" global n0\n",
......@@ -185,13 +186,13 @@
" if container_gg is None:\n",
" # plot g = s * h\n",
" ax = axs[1]\n",
" container_gg = ient_stem(ax, m, g_plot)\n",
" container_gg = rwth_plots.stem(ax, m, g_plot)\n",
" \n",
" if container_ss is not None:\n",
" # update data\n",
" ient_stem_set_ydata(container_ss, s(m))\n",
" ient_stem_set_ydata(container_hh, h(n-m))\n",
" ient_stem_set_ydata(container_gg, g_plot)\n",
" rwth_plots.stem_set_ydata(container_ss, s(m))\n",
" rwth_plots.stem_set_ydata(container_hh, h(n-m))\n",
" rwth_plots.stem_set_ydata(container_gg, g_plot)\n",
" \n",
" # update labels\n",
" ax = axs[0]\n",
......@@ -202,33 +203,33 @@
" else:\n",
" # plot s and h\n",
" ax = axs[0]; # s and h axis\n",
" container_ss = ient_stem(ax, m, s(m), 'grun', label=r'$s(m)$')\n",
" container_ss = rwth_plots.stem(ax, m, s(m), 'rwth:green', label=r'$s(m)$')\n",
" container_ss[0].set_markerfacecolor('none'); \n",
" container_ss[0].set_markersize(8); \n",
" container_ss[0].set_markeredgewidth(2);\n",
" container_hh = ient_stem(ax, m, h(n-m), 'rwth', label=r'$h(n-m)$')\n",
" container_hh = rwth_plots.stem(ax, m, h(n-m), 'rwth:blue', label=r'$h(n-m)$')\n",
" \n",
" # configure axis settings\n",
" ax.set_xlabel(r'$\\rightarrow m$');\n",
" ax.set_xlim([-10.2,10.2]); \n",
" ax.set_xticks(np.arange(-10, 11, step=2))\n",
" ax.legend(); ient_grid(ax); ient_axis(ax);\n",
" ient_annotate_xtick(ax, r'$n$', n, -0.1, 'rwth', 15); # mark n on m axis\n",
" ax.legend(); rwth_plots.grid(ax); rwth_plots.axis(ax);\n",
" rwth_plots.annotate_xtick(ax, r'$n$', n, -0.1, 'rwth:blue', 15); # mark n on m axis\n",
" \n",
" # configure g axis settings\n",
" ax = axs[1]\n",
" ax.set_xlabel(r'$\\rightarrow n$'); ax.set_ylabel(r'$\\uparrow g(n)=s(n)\\ast h(n)$');\n",
" ax.set_xlim(axs[0].get_xlim())\n",
" ax.set_xticks(np.arange(-10, 11, step=2))\n",
" ient_grid(ax); ient_axis(ax);\n",
" ient_annotate_xtick(ax, r'$n$', n, np.min(ax.get_ylim()), 'black', 15);\n",
" rwth_plots.grid(ax); rwth_plots.axis(ax);\n",
" rwth_plots.annotate_xtick(ax, r'$n$', n, np.min(ax.get_ylim()), 'black', 15);\n",
" ax.plot([n, n], [0, gn[n_ind]], 'ko--', lw=1);\n",
" \n",
" # update limits\n",
" if np.all(gn>0):\n",
" gn[0] = 0\n",
" ient_update_ylim(axs[0], np.concatenate([s(m), h(n-m)]), .19, ymax = 1e3)\n",
" ient_update_ylim(axs[1], gn, np.max(np.abs(gn))/10, ymax = 1e3)"
" rwth_plots.update_ylim(axs[0], np.concatenate([s(m), h(n-m)]), .19, ymax = 1e3)\n",
" rwth_plots.update_ylim(axs[1], gn, np.max(np.abs(gn))/10, ymax = 1e3)"
]
},
{
......
%% Cell type:code id: tags:
``` python
# Copyright 2020 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
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal # convolution
from ient_nb.ient_plots import *
from ient_nb.ient_signals import *
import rwth_nb.plots.mpl_decorations as rwth_plots
from rwth_nb.misc.signals import *
```
%% Cell type:markdown id: tags:
<div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
<img src="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
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
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)$
* Eigene Kreation
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.
Zusätzlich zu Elementarsignalen kann auch eine frei definierbare Funktion $s_0(n)$ zur Faltung verwendet werden.
%% Cell type:code id: tags:
``` python
s_0 = lambda n: gauss(n)*unitstep(n)
```
%% Cell type:code id: tags:
``` python
n = np.linspace(-10, 10, 21)
m = np.linspace(-40, 40, 81) # m Achse
n0 = -2
container_s = container_h = None
def convolution(s, h):
# Convolve s and h numerically
return signal.convolve(s(m), h(m), mode='same')
signal_types = {'Dirac-Impuls' : lambda n, b, M: np.where(n==0, 1, 0),
'Sprungfunktion' : lambda n, b, M: np.where(n>=0, 1, 0),
'Exponentialimpuls' : lambda n, b, M: unitstep(n)*b**n,
'Rechteck' : lambda n, b, M: unitstep(n+M) - unitstep(n-M-1),
'Eigene Kreation s0(n)' : lambda n, b, M: s_0(n)
}
fig0, axs0 = plt.subplots(1, 2, figsize=(ient_fig_width, ient_fig_width/4));
fig0, axs0 = plt.subplots(1, 2, figsize=(rwth_plots.fig_width, rwth_plots.fig_width/4));
def update_signals(s_type, s_n0, h_type, h_n0, b_s, b_h, M_s, M_h):
# show widgets according to chosen s and h
w_b_s.layout.visibility = 'visible' if s_type == 'Exponentialimpuls' else 'hidden'; w_M_s.layout.visibility = 'visible' if s_type == 'Rechteck' else 'hidden'
w_b_h.layout.visibility = 'visible' if h_type == 'Exponentialimpuls' else 'hidden'; w_M_h.layout.visibility = 'visible' if h_type == 'Rechteck' else 'hidden'
# calculate s(m-n0) and h(m-n0)
global s, h, gn, container_s, container_h # reused in second interactive plot
s = lambda m: signal_types[s_type]((m-s_n0), b_s, M_s); # s(m-n0)
h = lambda m: signal_types[h_type]((m-h_n0), b_h, M_h); # h(m-n0)
gn = convolution(s, h) # numerical convolution
# update second plot if existing
try:
global n0
update_plot(n0)
except NameError:
pass
# display s and h plots
if container_s is None:
# plot s
ax = axs0[0];
container_s = ient_stem(ax, m, s(m), 'rwth')
container_s = rwth_plots.stem(ax, m, s(m), 'rwth:blue')
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]); ient_axis(ax); ient_grid(ax);
ax.set_xlim([-10.9, 10.9]); rwth_plots.axis(ax); rwth_plots.grid(ax);
# plot h
ax = axs0[1];
container_h = ient_stem(ax, m, h(m), 'rwth')
container_h = rwth_plots.stem(ax, m, h(m), 'rwth:blue')
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()); ient_axis(ax); ient_grid(ax);
ax.set_xlim(axs0[0].get_xlim()); rwth_plots.axis(ax); rwth_plots.grid(ax);
else:
ient_stem_set_ydata(container_s, s(m))
ient_stem_set_ydata(container_h, h(m))
rwth_plots.stem_set_ydata(container_s, s(m))
rwth_plots.stem_set_ydata(container_h, h(m))
# update limits
ient_update_ylim(axs0[0], s(m), .19)
ient_update_ylim(axs0[1], h(m), .19)
rwth_plots.update_ylim(axs0[0], s(m), .19)
rwth_plots.update_ylim(axs0[1], h(m), .19)
# Widgets
w_s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(n)$:', style=ient_wdgtl_style)
w_s_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=ient_wdgtl_style)
w_h_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $h(n)$:', style=ient_wdgtl_style)
w_h_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=ient_wdgtl_style)
w_b_s=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_s$', style=ient_wdgtl_style)
w_b_h=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_h$', style=ient_wdgtl_style)
w_M_s=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_s$', style=ient_wdgtl_style)
w_M_h=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_h$', style=ient_wdgtl_style)
w_s_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $s(n)$:', style=rwth_plots.wdgtl_style)
w_s_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=rwth_plots.wdgtl_style)
w_h_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $h(n)$:', style=rwth_plots.wdgtl_style)
w_h_n0=widgets.FloatSlider(min=-5, max=5, value=0, step=1, description=r'Verschiebung $n_0$', style=rwth_plots.wdgtl_style)
w_b_s=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_s$', style=rwth_plots.wdgtl_style)
w_b_h=widgets.FloatSlider(min=.1, max=1, value=.5, step=.1, description=r'$b_h$', style=rwth_plots.wdgtl_style)
w_M_s=widgets.FloatSlider(min=0, max=5, value=1, step=1, description=r'$M_s$', style=rwth_plots.wdgtl_style)
w_M_h=widgets.FloatSlider(min=0, max=5, value=1, step