Commit 92a8967f authored by Christian Rohlfing's avatar Christian Rohlfing
Browse files

- split Laplace into example and gui

- added sin to abtastung
parent 55723422
%% Cell type:code id: tags:
``` python
# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget
from ipywidgets import interact, interactive, fixed, HBox, VBox
import ipywidgets as widgets
from IPython.display import clear_output, display, HTML
from src.sampling.sampling_plot import SamplingPlot
from ient_nb.ient_plots import *
from ient_nb.ient_transforms 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>
# Ideale Abtastung
Dieses Notebook soll die ideale Abtastung veranschaulichen.
![Blockdiagramm](figures/sampling_block_diagram.png)
Das zeitkontinuierliche Signal $s(t)$ wird zu Zeitpunkten $nT$ mit Abtastperiode $T$ abgetastet. Das resultierende, ideal abgetastete Signal
$$s_\mathrm{a}(t) = \sum\limits_{n=-\infty}^\infty s(nT) \delta(t-nT)$$
besteht aus Dirac-Impulsen, positioniert an den Zeitpunkten $nT$ und gewichtet mit dem Funktionswerten $s(nT)$. Die zugehörige Fourier-Transformierte $S_{\mathrm{a}}(f)$ wird aus periodischen Wiederholungen des Signalspektrums $S(f)$ zusammengesetzt:
$$S_\mathrm{a}(f) = \frac{1}{T}\sum\limits_{k=-\infty}^\infty S\left(f-\frac{k}{T}\right) \text{.}$$
Die Wiederholungen sind bei Vielfachen der Abtastrate $r=\frac{1}{T}$ positioniert.
Zur Rückgewinnung wird ein Rekonstruktionsfilter $h_\mathrm{TP}(t)$ eingesetzt, welches im Idealfall die die spektrale Kopie bei $k=0$ (auch Basisband genannt) aus $S_\mathrm{a}(f)$ rekonstruieren soll.
Hier wird das ideale Tiefpassfilter
$$H_\mathrm{TP}(f)=\mathrm{rect}\left(\frac{f}{2 f_\mathrm{g}}\right)$$ mit Grenzfrequenz $f_\mathrm{g} = \frac{r}{2}$ verwendet.
%% Cell type:markdown id: tags:
Zur Auswahl stehen vier Signale $s(t)$:
## Demo
Im Folgenden wird ein ideales Abtastsystem mit fester Abtastrate $r=2$ angenommen. Das ideale Rekonstruktionsfilter wird mit $f_\mathrm{g} = \frac{r}{2} = 1$ verwendet.
Zur Auswahl stehen die folgenden Signale $s(t)$, deren Frequenz $F$ variabel ist.
* $s(t) = \cos(2 \pi F t)$ mit $S(f) = \frac{1}{2}\delta(f-F)+\frac{1}{2}\delta(f+F)$,
* $s(t) = \sin(2 \pi F t)$ mit $S(f) = \frac{1}{2\mathrm{j}}\delta(f-F)-\frac{1}{2\mathrm{j}}\delta(f+F)$,
* $s(t) = \mathrm{si}(2 \pi F t)$ mit $S(f) = \frac{1}{2 |F|}\mathrm{rect}\left(\frac{f}{2F}\right)$,
* $s(t) = \mathrm{rect} (F t)$ mit $S(f) = \frac{1}{|F|}\mathrm{si}\left(\frac{\pi f}{F}\right)$ und
* $s(t) = \Lambda(F t)$ mit $S(f) = \frac{1}{|F|}\mathrm{si}^2\left(\frac{\pi f}{F}\right)$.
Achtung: Die letzten beiden Signale $s(t)$, Rechteck- und Dreieckimpuls, haben unendlich ausgedehnte Spektren $S(f)$. Daher ist eine fehlerfreie Rekonstruktion prinzipiell nicht möglich!
Zunächst werden $s(t)$ und $s_\mathrm{a}(t)$ im Zeitbereich betrachtet. Weiterhin wird das zu $s_\mathrm{a}(t)$ gehörige Spektrum $S_\mathrm{a}(f)$ dargestellt. In der gleichen Abbildung ist die Übertragungsfunktion $H_\mathrm{TP}(f)$ des Rekonstruktionsfilters gezeigt. In der letzten Abbildung wird nun das rekonstruierte Signal $g(t)$ gezeigt. Im Alias-freien Fall für cos-Funktion und si-Funktion gilt $g(t)=s(t)$.
Zunächst werden $s(t)$ und $s_\mathrm{a}(t)$ im Zeitbereich betrachtet. Weiterhin wird das zu $s_\mathrm{a}(t)$ gehörige Spektrum $S_\mathrm{a}(f)$ dargestellt. In der gleichen Abbildung ist die Übertragungsfunktion $H_\mathrm{TP}(f)$ des Rekonstruktionsfilters gezeigt. In der letzten Abbildung wird nun das rekonstruierte Signal $g(t)$ gezeigt. Im Alias-freien Fall für cos-, sin- und si-Funktion gilt $g(t)=s(t)$.
%% Cell type:code id: tags:
``` python
r = 2; T = 1/r; # sampling frequency
signals_t = {'cos-Funktion': lambda t: np.cos(2 * np.pi * t),
'sin-Funktion': lambda t: np.sin(2 * np.pi * t),
'si-Funktion': lambda t: si(2 * np.pi * t),
'Rechteckimpuls': lambda t: rect(t / 1.05),
'Dreieckimpuls': tri}
signals_f = {'cos-Funktion': lambda f, F: np.isin(f/F, f[findIndOfLeastDiff(f/F, [-1, 1])]/F) * 0.5,
'sin-Funktion': lambda f, F: np.isin(f/F, f[findIndOfLeastDiff(f/F, [1])]/F) / 2j - np.isin(f/F, f[findIndOfLeastDiff(f/F, [-1])]/F) / 2j,
'si-Funktion': lambda f, F: 1/(2*np.abs(F))*rect(f / (2*F)),
'Rechteckimpuls': lambda f, F: 1/np.abs(F)*si(np.pi * f / F),
'Dreieckimpuls': lambda f, F: 1/np.abs(F)*si(np.pi * f/F) ** 2}
#f = t;
t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis
f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis
kMax = 16 # number of k values in sum for Sa(f)
# Plot
plt.close(); fig, axs = plt.subplots(3, 1)
plt.close(); fig, axs = plt.subplots(4, 1); fig.canvas.layout.height = '800px'; plt.tight_layout();
@widgets.interact(s_type=widgets.Dropdown(options=list(signals_t.keys()), description=r'Wähle $s(t)$:'),
F=widgets.FloatSlider(min=0.1, max=2, value=0.9, step=.1, description=r'$F$', style=ient_wdgtl_style))
F=widgets.FloatSlider(min=0.1, max=2, value=0.9, step=.1, description=r'$F$', style=ient_wdgtl_style, continuous_update=False))
def update_plots(s_type, F):
s = lambda t: signals_t[s_type](t*F);
S = lambda f: signals_f[s_type](f, F);
nT, snT = ient_sample(t, s(t), T)
# Construct sampled spectrum
Sa = np.zeros_like(f)
Sa = np.zeros_like(S(f))
for k in np.arange(-kMax, kMax+1): # evaluate infinite sum only for 2*kMax+1 elements
Sa += S(f-k/T)
Sa = Sa/T
# Reconstruct g(t)
H_lp = rect(f/(r+0.001)) # reconstruction filter
G = Sa * H_lp * T; # reconstruction
g = ient_idft(G);
g = np.fft.ifftshift(np.real(g)); # IDFT
if not s_type == 'cos-Funktion':
g /= (len(f)/(2*f[-1])) # Parseval :)
else:
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
fSadirac = f[np.where(Sa)]; Sadirac = Sa[np.where(Sa)]
fSdirac = f[np.where(S(f))]; Sdirac = S(f)[np.where(S(f))]
fGdirac = f[np.where(G)]; Gdirac = G[np.where(G)]
if s_type == 'sin-Funktion':
Sadirac = np.imag(Sadirac); Sdirac = np.imag(Sdirac); S = lambda f: np.imag(signals_f[s_type](f, F)); Sa = np.imag(Sa); G = np.imag(G); Gdirac = np.imag(Gdirac)
axs[1].lines[1].set_label(r'$\mathrm{Im}\{S_\mathrm{a}(f)\}$'); axs[1].lines[-3].set_label(r'$\mathrm{Im}\{S(f)\}$');
axs[1].legend(loc=2);
axs[2].set_ylabel(r'$\uparrow \mathrm{Im}\{G(f)\}$');
else:
if axs[1].lines:
axs[1].lines[1].set_label(r'$S_\mathrm{a}(f)$'); axs[1].lines[-3].set_label(r'$S(f)$')
axs[1].legend(loc=2)
axs[2].set_ylabel(r'$\uparrow G(f)$');
else:
g /= (len(f)/(2*f[-1])) # Parseval :)
# Plot
if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time
ax = axs[0]; ax.set_title('Zeitbereich');
ax.plot(t, s(t), color='rwth', linestyle='--', label=r'$s(t)$');
ient_plot_dirac(ax, nT, snT, 'rot', label=r'$s_\mathrm{a}(t)$')
ax.set_xlabel(r'$\rightarrow t$');
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);
ax = axs[1]; ax.set_title('Frequenzbereich');
ax.plot(f, H_lp, '-', color='black', label=r'$H_\mathrm{TP}(f)$')
if not s_type == 'cos-Funktion':
ax.plot(f, Sa, '-', color='rot', label=r'$S_a(f)$');
ient_plot_dirac(ax, [], [], 'rot');
else:
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ax.plot(f, np.ones_like(f)*np.nan, '-', color='rot', label=r'$S_a(f)$');
ient_plot_dirac(ax, fSadirac, Sadirac, 'rot');
else:
ax.plot(f, Sa, '-', color='rot', label=r'$S_a(f)$');
ient_plot_dirac(ax, [], [], 'rot');
ax.plot(f, S(f), color='rwth', linestyle='--', linewidth=1, label=r'$S(f)$')
ax.set_xlim([-7.5,7.5]); ax.set_ylim([-1,2]); ax.legend(loc=2);
ax.set_xlabel(r'$\rightarrow f$'); ient_grid(ax); ient_axis(ax);
txt,_=ient_annotate_xtick(ax, r'$r=2$', r, -.1, 'black'); txt.get_bbox_patch().set_alpha(1);
txt,_=ient_annotate_xtick(ax, r'$f_\mathrm{g}$', r/2, -.1, 'black'); txt.get_bbox_patch().set_alpha(1);
txt,_=ient_annotate_xtick(ax, r'$r=2$', r, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);
txt,_=ient_annotate_xtick(ax, r'$f_\mathrm{g}$', r/2, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);
ax = axs[2];
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ax.plot(f, np.ones_like(f)*np.nan, '-', color='grun');
ient_plot_dirac(ax, fGdirac, Gdirac, 'grun');
else:
ax.plot(f, G, '-', color='grun');
ient_plot_dirac(ax, [], [], 'rot');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow G(f)$');
ax.set_xlim([-7.5,7.5]); ient_grid(ax); ient_axis(ax);
ax = axs[2]; ax.set_title('Zeitbereich (nach Rekonstruktion)');
ax = axs[3]; ax.set_title('Zeitbereich (nach Rekonstruktion)');
ax.plot(t, s(t), color='rwth', linestyle='--', label=r'$s(t)$');
ax.plot(t/deltat/(f[-1]*2), g, 'grun', label=r'$g(t)$');
ax.set_xlabel(r'$\rightarrow t$');
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);
plt.tight_layout()
else:
axs[0].lines[0].set_ydata(s(t))
ient_dirac_set_data(axs[0].containers, nT, snT)
if not s_type == 'cos-Funktion':
ient_dirac_set_data(axs[1].containers, [], [])
axs[1].lines[1].set_ydata(Sa);
else:
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ient_dirac_set_data(axs[1].containers, fSadirac, Sadirac);
axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan);
else:
ient_dirac_set_data(axs[1].containers, [], [])
axs[1].lines[1].set_ydata(Sa);
axs[1].lines[-3].set_ydata(S(f));
axs[2].lines[0].set_ydata(s(t))
axs[2].lines[1].set_ydata(g);
ient_update_ylim(axs[1], Sa, 0.19, np.max(Sa));
ient_update_ylim(axs[2], g, 0.19, np.max(g));
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ient_dirac_set_data(axs[2].containers, fGdirac, Gdirac);
axs[2].lines[0].set_ydata(np.ones_like(f)*np.nan);
else:
ient_dirac_set_data(axs[2].containers, [], [])
axs[2].lines[0].set_ydata(G);
axs[3].lines[0].set_ydata(s(t))
axs[3].lines[1].set_ydata(g);
ient_update_ylim(axs[1], Sa, 0.19, np.max(Sa)); ient_update_ylim(axs[2], G, 0.19, np.max(G));
ient_update_ylim(axs[3], np.concatenate((s(t),g)), 0.19, np.max(np.concatenate((s(t),g))));
```
%% 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:
*Emin Kosar, 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.
......
%% 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
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 Faltung
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
## Einleitung
Im Folgenden wird das Faltungsintegral
$$g(t)
= s(t)\ast h(t)
= \int\limits_{-\infty}^{\infty} s(\tau) h(t-\tau) \,\mathrm{d}\tau
$$
betrachtet.
%% Cell type:markdown id: tags:
## Demo
Wähle $s(t)$ und $h(t)$ sowie jeweils Verschiebung $t_0$ und Dehnungsfaktor $T$ für beide Signale: $s\left(\frac{t-t_0}{T}\right)$ und $h\left(\frac{t-t_0}{T}\right)$.
Zusätzlich zu Elementarsignalen kann auch eine frei definierbare Funktion $s_0(t)$ zur Faltung verwendet werden.
%% Cell type:code id: tags:
``` python
s_0 = lambda t: rect(t/2-1/2)*(-t)
```
%% Cell type:code id: tags:
``` python
def convolution(s, h):
# Convolve s and h numerically
return signal.convolve(s(tau), h(tau), mode='same')*deltat
(tau,deltat) = np.linspace(-20, 20, 4001, retstep=True) # tau Achse
(tau,deltat) = np.linspace(-15, 15, 5001, retstep=True) # tau Achse
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 s0(t)' : s_0,
}
# Plot
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),
h_type=widgets.Dropdown(options=list(signal_types.keys()), description=r'Wähle $h(t)$:'),
h_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=ient_wdgtl_style),
h_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=ient_wdgtl_style))
def update_signals(s_type, s_T, s_t0, h_type, h_T, h_t0):
global s, h, gt # reused in second interactive plot
s = lambda tau: signal_types[s_type]((tau-s_t0)/s_T);
h = lambda tau: signal_types[h_type]((tau-h_t0)/h_T);
gt = convolution(s, h) # numerical convolution
if not axs0[0].lines: # plot s(t) and g(t)
ax = axs0[0]; ax.plot(tau, s(tau), 'rwth');
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 = axs0[1]; ax.plot(tau, h(tau), 'rwth');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow h(t)$')
ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); ient_axis(ax); ient_grid(ax);
else: # update lines
axs0[0].lines[0].set_ydata(s(tau));
axs0[1].lines[0].set_ydata(h(tau));
try: # if convolution figure is already opened, update s(tau)
if axs[0].lines:
axs[0].lines[1].set_ydata(s(tau));
ient_update_ylim(axs[0], np.concatenate((h(tau), s(tau))), 0.19, 5); ient_update_ylim(axs[1], gt, 0.19, 5);
update_plot(-2) # update convolution plot
except: pass
ient_update_ylim(axs0[0], s(tau), 0.19, 5); ient_update_ylim(axs0[1], h(tau), 0.19, 5);
```
%% Cell type:markdown id: tags:
... und betrachte hier das Faltungsergebnis:
%% Cell type:code id: tags:
``` python
fig, axs = plt.subplots(2, 1, figsize=(8,6),) # gridspec_kw = {'width_ratios':[3, 1]}
@widgets.interact(t=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description='Verschiebung $t$', style=ient_wdgtl_style),
show_integrand=widgets.Checkbox(value=True, description='Zeige Integrand', style=ient_wdgtl_style))
def update_plot(t, show_integrand=True):
t_ind = np.where(tau>=t); t_ind = t_ind[0][0]; g_plot = gt.copy(); g_plot[t_ind:] = np.nan; # hide g(t') with t'>t
sh = s(tau)*h(t-tau) # integrand
if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time
ax = axs[0]; ax.plot(tau, h(t-tau), 'rwth', label=r'$h(t-\tau)$'); # plot h(t-tau)
ax.plot(tau, s(tau), 'grun', label=r'$s(\tau)$'); # plot s(tau)
ax.plot(tau, sh, '--', color='orange', lw=1, label=r'$s(\tau)h(t-\tau)$'); # plot integrand
ient_annotate_xtick(ax, r'$t$', t, -0.1, 'rwth', 15); # mark t on tau axis
ax.fill_between(tau, 0, sh, facecolor="none", hatch="//", edgecolor='k', linewidth=0.0); # hatch common area
ax.set_xlabel(r'$\rightarrow \tau$');
ax.set_xlim([-4.2,4.2]); ient_update_ylim(ax, np.concatenate((h(tau), s(tau))), 0.19, 5);
ax.legend(); ient_grid(ax); ient_axis(ax);
ax = axs[1]; ax.plot(tau, g_plot); # plot g(t)
ax.plot([t, t], [0, gt[t_ind]], 'ko--', lw=1);
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow g(t)=s(t)\ast h(t)$');
ax.set_xlim(axs[0].get_xlim()); ient_update_ylim(ax, gt, 0.19, 5);
ient_grid(ax); ient_axis(ax); fig.tight_layout(); #plt.subplots_adjust(wspace=.1,hspace=.1)
else: # Replace only xdata and ydata since plt.plot() takes longer time
ax = axs[0]; ax.lines[0].set_ydata(h(t-tau)); ax.lines[2].set_ydata(sh); # update signals
ax.texts[0].set_x(t); ax.lines[3].set_xdata([t,t]) # update labels
if ax.collections: ax.collections[0].remove(); # update integrand
if show_integrand: ax.fill_between(tau,0,sh, facecolor="none", hatch="//", edgecolor='k', linewidth=0.0);
ax = axs[1]; ax.lines[0].set_ydata(g_plot); # update signals
ax.lines[1].set_xdata([t, t]); ax.lines[1].set_ydata([0, gt[t_ind]]); # update labels
axs[0].lines[2].set_visible(show_integrand)
```
%% Cell type:markdown id: tags:
### Aufgaben:
* Bewege den Schieberegler für $t$ und betrachte das entstehende Faltungsintegral. Wie sind die zugehörigen Integralsgrenzen und welche Intervalle (vgl. Notebook zur Faltung) sind zu beobachten?
* Wähle zwei Rechtecke unterschiedlicher Breite aus. Wie sieht das entstehende Signal aus? Wie breit ist es? Was passiert, wenn eins der Rechtecke um $t_0$ verschoben wird?
* Welche Höhe bei $t=0$ hat das Resultat der Faltung $g(t) = \mathrm{rect}\left(\frac{t}{2}\right)\ast \mathrm{rect}\left(\frac{t}{2}\right)$? Überprüfe die Überlegungen mit Hilfe der entsprechenden Funktionen in der Demo.
* Gilt das Kommutativgesetz $s(t) \ast h(t) = h(t) \ast s(t)$?
* Wie sieht das Faltungsergebnis zweier Si-Funktionen aus? Wie das Ergebnis zweier Gaußfunktionen?
* Wie sieht das Faltungsergebnis zweier si-Funktionen aus? Wie das Ergebnis zweier Gaußfunktionen?
* Reale Rechteckimpulse weisen nur eine endliche Flankensteilheit auf. Diese können beispielsweise mit $s(t)=\mathrm{rect}(t)*\mathrm{rect}(t/T)$ oder $s(t)=\mathrm{rect}(t)*\Lambda(\frac{t}{T})$ beschrieben werden. Betrachte diese Fälle für $|T|<\frac{1}{2}$. Wie hängen Gesamtdauer und Dauer der Anstiegsflanke von $T$ ab?
%% 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.
......
%% 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
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 *
from ient_nb.ient_transforms import *
eps = np.finfo(float).eps
```
%% Cell type:markdown id: tags:
<div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Demonstrator Fourier-Transformation
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:code id: tags:
``` python
(t,deltat) = np.linspace(-20, 20, 50001, retstep=True) # t Achse
f = t; deltaf=deltat;
signal_types_t = {'Rechteck' : rect,
'Dreieck' : tri,
'si-Funktion' : lambda t: si(2*np.pi*t),
'Gauß-Signal' : gauss}
signal_types_f = {'Rechteck' : lambda f,T: np.abs(T)*si(np.pi*T*f),
'Dreieck' : lambda f,T: np.abs(T)*si(np.pi*T*f)**2,
'si-Funktion' : lambda f,T: np.abs(T)/2*rect(f*T/2),
'Gauß-Signal' : lambda f,T: np.abs(T)*gauss(f*T)}
# Plot
plt.close(); fig, axs = plt.subplots(3, 1)
@widgets.interact(s_type=widgets.Dropdown(options=list(signal_types_t.keys()), description=r'Wähle $s(t)$:'),
T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=r'Dehnung T', style=ient_wdgtl_style),
t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=r'Verschiebung $t_0$', style=ient_wdgtl_style))
def update_signals(s_type, T, t0):
s = lambda t: signal_types_t[s_type]((t-t0)/T);
S = lambda f: signal_types_f[s_type](f, T)*np.exp(-2j*np.pi*f*t0)
Sabs = np.abs(S(f));
Sangle = np.angle(S(f)); Sangle[Sabs < eps] = 0;
if not axs[0].lines: # plot s(t)
ax = axs[0]; ax.plot(t, s(t), 'rwth');
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 = axs[1]; ax.plot(f, Sabs, 'rwth');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow |S(f)|$')
ax.set_xlim([-20,20]); ient_axis(ax); ient_grid(ax);
ax = axs[2]; ax.plot(f, Sangle, 'rwth');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow \angle S(f)$')
ax.set_xlim([-20,20]); ax.set_ylim([-4, 4]); ient_axis(ax); ient_grid(ax); ax.set_yticks([-np.pi, np.pi]); ax.yaxis.set_ticklabels([r'$-\pi$', r'$\pi$'])
else: # update lines
axs[0].lines[0].set_ydata(s(t));
axs[1].lines[0].set_ydata(Sabs)
axs[2].lines[0].set_ydata(Sangle)
ient_update_ylim(axs[0], s(t), 0.19, np.max(s(t))); ient_update_ylim(axs[1], Sabs, 0.19, np.max(Sabs));
```
%% Cell type:code id: tags:
``` python
#t0 = 0.1
#z = np.exp(-2j*np.pi*f*t0)
#
## Plot
#fig,ax=plt.subplots();
#ax.plot(f, np.angle(z), 'rwth')
#ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow \angle \mathrm{e}^{-\mathrm{j}2\pi f t_0}$'); ient_axis(ax)
```
%% 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.
......
%% Cell type:code id: tags:
``` python