Verified Commit fe0f5f33 authored by Christian Rohlfing's avatar Christian Rohlfing
Browse files

disabled strange masked array to nan conversion warning

parent ad6587ce
Pipeline #555606 passed with stage
in 3 minutes and 19 seconds
%% 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
from IPython.display import clear_output, display, HTML
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal # convolution
import rwth_nb.plots.mpl_decorations as rwth_plots
import rwth_nb.misc.transforms as rwth_transforms
from rwth_nb.misc.signals import *
import warnings
warnings.simplefilter("ignore", UserWarning) # TODO: strange masked array to nan warning
```
%% Cell type:markdown id: tags:
<div>
<img src="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.
Die Fouriertransformierte eines Signals $s(t)$ ist definiert als
$$
\displaystyle S(f)=\int\limits_{-\infty}^{\infty}s(t)\mathrm{e}^{-j2\pi ft}\mathrm{d}t
$$
Im Allgemeinen kann angenommen werden, dass $S(f)$ komplexwertig ist. Es lässt sich somit in den Betrag der Übertragungsfunktion $|S(f)|$ und die Phase $\varphi(f)$ zerlegen.
Dieser Demonstrator veranschaulicht, wie sich die Fouriertransformierte eines Signals $s(t)$ in Betrag und Phase verhält.
Im Drop-Down Menü für $s(t)$ kann zwischen fünf verschiedenen Funktionen ausgewählt werden. Die zur Verfügung stehenden Funktionen sind
* Rechteck
* Dreieck
* Dirac
* si-Funktion
* Gauß-Signal
Über den Slider für die Dehnung $T_0$ des Signals kann die Breite des Signals angepasst werden, über die Verschiebung $t_0$ kann die Position des Signals geändert werden.
%% 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,
'Dirac' : lambda t: [1],
'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,
'Dirac' : lambda f,T: np.abs(T),
'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); plt.tight_layout();
@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=rwth_plots.wdgtl_style),
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, 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:blue');
rwth_plots.plot_dirac(axs[0], [], [])
rwth_plots.dirac_weights(axs[0],0,1,2);axs[0].texts[0].set_text('');
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]); rwth_plots.axis(ax); rwth_plots.grid(ax);
ax = axs[1]; ax.plot(f, Sabs, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow |S(f)|$')
ax.set_xlim([-20,20]); rwth_plots.axis(ax); rwth_plots.grid(ax);
ax = axs[2]; ax.plot(f, Sangle, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow \angle S(f)$')
ax.set_xlim([-20,20]); ax.set_ylim([-4, 4]); rwth_plots.axis(ax); rwth_plots.grid(ax); ax.set_yticks([-np.pi, np.pi]); ax.yaxis.set_ticklabels([r'$-\pi$', r'$\pi$'])
else: # update lines
if s_type == 'Dirac':
axs[0].lines[0].set_ydata(0)
rwth_plots.dirac_set_data(axs[0].containers, [t0], [np.abs(T)])
axs[1].lines[0].set_ydata(Sabs)
axs[0].set_ylim(0, np.abs(T)*1.5); axs[1].set_ylim(0, np.abs(T)*1.5)
axs[0].texts[0].set_text('({})'.format(np.abs(T))); axs[0].texts[0].set_x(t0); axs[0].texts[0].set_y(np.abs(T))
else:
rwth_plots.dirac_set_data(axs[0].containers, [], [])
axs[0].lines[0].set_ydata(s(t));
axs[1].lines[0].set_ydata(Sabs)
rwth_plots.update_ylim(axs[0], s(t), 0.19, np.max(s(t))); rwth_plots.update_ylim(axs[1], Sabs, 0.19, np.max(Sabs));
axs[0].texts[0].set_text('')
axs[2].lines[0].set_ydata(Sangle)
```
%% Cell type:markdown id: tags:
## Aufgaben
Wähle für $s(t)$ ein Rechteck aus.
* Variiere die Breite $T$, während die Verschiebung konstant gehalten wird. Was passiert mit Betrag und Phase des Spektrums? Wo sind die Sprünge in der Phase zu finden?
* Betrachte ein Rechteck der Breite $T=1$. Variiere die Verschiebung $t_0$ und beobachte, was sich ändert. Wieso passiert das?
* Betrachte die Phase für $t_0=0.5$ und $t_0=-0.5$. Was macht die Phase?
Wähle nun ein Dreieck für $s(t)$.
* Wie sieht der Betrag der Phase nun aus im Vergleich? Warum?
* Wie ändert sich die Phase, wenn das Dreieck verschoben wird?
Wähle nun einen Dirac als Funktion aus.
* Ändere die Verschiebung $t_0$. Was passiert mit Betrag und Phase des Spektrums?
* Ändere die Dehnung $T$. Was passiert nun?
Wähle nun die si-Funktion aus.
* Vergleiche mit dem Ergebnis für das Rechteck. Wieso ist das so?
* Ändere $T$. Was passiert mit der Phase?
Wähle nun ein Gauß-Signal.
* Was passiert hier mit der Phase, wenn $T$ und $t_0$ geändert werden?
%% 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.
......
%% Cell type:code id: tags:
``` python
# Copyright 2020 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
import matplotlib.pyplot as plt
import numpy as np
import rwth_nb.plots.mpl_decorations as rwth_plots
import rwth_nb.misc.transforms as rwth_transforms
from rwth_nb.misc.signals import *
import warnings
warnings.simplefilter("ignore", UserWarning) # TODO: strange masked array to nan warning
```
%% Cell type:code id: tags:
``` python
t = np.linspace(-10, 10, 10001); f = np.linspace(-10, 10, 10001) # time and frq domain
s = tri # use predefined triangle function from ient_signals
S = lambda f: np.sinc(5*f/np.pi) # alternatively define own signals
def x_mirrored_around_zero(maxval, inc=1):
x = np.arange(inc, maxval + inc, inc)
return np.r_[-x[::-1], 0, x]
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Ideale Abtastung
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
## Einleitung
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 den 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 und mit $r=\frac{1}{T}$ gewichtet.
Zur Rückgewinnung wird ein Rekonstruktionsfilter $h_\mathrm{TP}(t)$ eingesetzt, welches im Idealfall 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.
Zur Rückgewinnung im Spektralbereich wird dieser ideale Tiefpass mit dem Spektrums des abgetasteten Signals $S_{\mathrm{a}}(f)$ multipliziert. Das Spektrum des rekonstruierten Signals ist somit
$$G(f)=S_\mathrm{a}(f) \cdot H_\mathrm{TP}(f) \cdot T\text{.}$$
Das rekonstuierte Signal im Zeitbereich $g(t)$ wird dann durch Rücktransformation gewonnen.
%% Cell type:markdown id: tags:
## 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.
Das Spektrum des rekonstruierten Signal $G(f)=S_\mathrm{a}(f) \cdot H_\mathrm{TP}(f) \cdot T$ wird in der nächsten Abbildung dargestellt.
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[find_ind_least_diff(f/F, [-1, 1])]/F) * 0.5,
'sin-Funktion': lambda f, F: np.isin(f/F, f[find_ind_least_diff(f/F, [1])]/F) / 2j - np.isin(f/F, f[find_ind_least_diff(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(4, 1, **rwth_plots.landscape); 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=rwth_plots.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 = rwth_transforms.sample(t, s(t), T)
# Construct sampled spectrum
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 = rwth_transforms.idft(G);
g = np.fft.ifftshift(np.real(g)); # IDFT
# Sample
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)
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:blue', linestyle='--', label=r'$s(t)$');
rwth_plots.plot_dirac(ax, nT, snT, 'rwth:red', label=r'$s_\mathrm{a}(t)$')
ax.set_xlabel(r'$\rightarrow t$');
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
ax = axs[1]; ax.set_title('Frequenzbereich');
ax.plot(f, H_lp, '-', color='black', label=r'$H_\mathrm{TP}(f)$')
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ax.plot(f, np.ones_like(f)*np.nan, '-', color='rwth:red', label=r'$S_a(f)$');
rwth_plots.plot_dirac(ax, fSadirac, Sadirac, 'rwth:red');
else:
ax.plot(f, Sa, '-', color='rwth:red', label=r'$S_a(f)$');
rwth_plots.plot_dirac(ax, [], [], 'rwth:red');
ax.plot(f, S(f), color='rwth:blue', 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$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
txt,_=rwth_plots.annotate_xtick(ax, r'$r=2$', r, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);
txt,_=rwth_plots.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='rwth:green');
rwth_plots.plot_dirac(ax, fGdirac, Gdirac, 'rwth:green');
else:
ax.plot(f, G, '-', color='rwth:green');
rwth_plots.plot_dirac(ax, [], [], 'rwth:red');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow G(f)=S_\mathrm{a}(f) \cdot H_\mathrm{TP}(f) \cdot T$', bbox=rwth_plots.wbbox);
ax.set_xlim([-7.5,7.5]); rwth_plots.grid(ax); rwth_plots.axis(ax);
ax = axs[3]; ax.set_title('Zeitbereich (nach Rekonstruktion)');
ax.plot(t, s(t), color='rwth:blue', linestyle='--', label=r'$s(t)$');
ax.plot(t/deltat/(f[-1]*2), g, 'rwth:green', label=r'$g(t)$');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
plt.tight_layout()
else:
axs[0].lines[0].set_ydata(s(t)); axs[1].lines[-3].set_ydata(S(f));
rwth_plots.dirac_set_data(axs[0].containers, nT, snT)
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': # dirac plot
rwth_plots.dirac_set_data(axs[1].containers, fSadirac, Sadirac); axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan);
rwth_plots.dirac_set_data(axs[2].containers, fGdirac, Gdirac); axs[2].lines[0].set_ydata(np.ones_like(f)*np.nan);
else:
axs[1].lines[1].set_ydata(Sa); rwth_plots.dirac_set_data(axs[1].containers, [], []);
axs[2].lines[0].set_ydata(G); rwth_plots.dirac_set_data(axs[2].containers, [], []);
axs[3].lines[0].set_ydata(s(t)); axs[3].lines[1].set_ydata(g);
if s_type == 'sin-Funktion': # Adapt labels
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[2].yaxis.label.set_text(r'$\uparrow \mathrm{Im}\{G(f)=S_\mathrm{a}(f) \cdot H_\mathrm{TP}(f) \cdot T\}$');
else:
axs[1].lines[1].set_label(r'$S_\mathrm{a}(f)$'); axs[1].lines[-3].set_label(r'$S(f)$')
axs[2].yaxis.label.set_text(r'$\uparrow G(f)=S_\mathrm{a}(f) \cdot H_\mathrm{TP}(f) \cdot T$');
axs[1].legend(loc=2)
rwth_plots.update_ylim(axs[1], Sa, 0.19, np.max(Sa)); rwth_plots.update_ylim(axs[2], G, 0.19, np.max(G));
rwth_plots.update_ylim(axs[3], np.concatenate((s(t),g)), 0.19, np.max(np.concatenate((s(t),g))));
```
%% Cell type:markdown id: tags:
## Aufgaben
* Wähle eine cos-Funktion für $s(t)$ und setze $F$ auf die kleinstmögliche Größe. Im Spektrum ist die Frequenz des Cosinus zu erkennen und im Zeitbereich wird dieser perfekt rekonstruiert. Erhöhe nun $F$ schrittweise. Beobachte das Spektrum. Was passiert und warum?
* Betrachte das Spektrum für $F=1$. Vergleiche die Höhe der Diracs mit denen für $F=0.9$ und $F=1.1$. Wie ist der Unterschied zu erklären?
* Für $F\geq 1$ wird das Signal nicht mehr perfekt rekonstruiert. Dieser Effekt nennt sich Aliasing. Wie verhält sich das rekonstruierte Signal bei größer werdendem $F$?
* Betrachte abschließend $F=2$. Was passiert hier?
* Wähle nun eine sin-Funktion und untersuche dieselben Dinge, wie zuvor für die cos-Funktion. Wie ist das Ergebnis für $F=1$ und $F=2$ zu erklären?
* Betrachte die si-Funktion. Das Spektrum der si-Funktion ist ein Rechteck. Was passiert, wenn $F$ größere Werte annimmt? Warum?
* Setze $F=1$. Kann aus $S_a(f)$ prinzipiell das ursprüngliche Signal rekonstruiert werden? Warum wird das Signal trotzdem perfekt rekonstruiert?
* Betrachte $F \leq 1$. Welche Form nimmt $G(f)$ an und wie wirkt sich das auf das rekonstruierte Signal aus?
Nun wird der Rechteckimpuls und der Dreiecksimpuls betrachtet. Im Gegensatz zu den vorherigen Funktionen ist das Spektrum hier, wie bereits oben erwähnt, unendlich ausgedehnt. Daher ist eine fehlerfreie Rekonstruktion prinzipiell nicht möglich.
* Starte wieder mit dem kleinstmöglichen $F$. Betrachte das Spektrum des abgetasteten Signals $S_{\mathrm{a}}(f)$ und das Spektrum nach Anwendung des Rekonstruktionsfilters $G(f)$. Wie müsste $G(f)$ für fehlerfreie Rekonstruktion aussehen? Was erzeugt den Unterschied?
* Erhöhe nun $F$ schrittweise und betrachte die Änderung von $S_{\mathrm{a}}(f)$, $G(f)$ und $g(t)$. Ab welchem $F$ ist das Ausgangssignal nicht mehr zu erkennen?
* Was passiert für $F \leq 1$ und wie erklärt sich das?
* Führe dieselben Überlegungen für den Dreiecksimpuls aus. Wie erklärt sich das unterschiedliche Verhalten?
%% 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, 2020, Institut für Nachrichtentechnik, RWTH Aachen University.
......
%% Cell type:code id: tags:
``` python
# Copyright 2020 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
import matplotlib.pyplot as plt
import numpy as np
import rwth_nb.plots.mpl_decorations as rwth_plots
import rwth_nb.misc.transforms as rwth_transforms
from rwth_nb.misc.signals import *
import warnings
warnings.simplefilter("ignore", UserWarning) # TODO: strange masked array to nan warning
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[find_ind_least_diff(f/F, [-1, 1])]/F) * 0.5,
'sin-Funktion': lambda f, F: np.isin(f/F, f[find_ind_least_diff(f/F, [1])]/F) / 2j - np.isin(f/F, f[find_ind_least_diff(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}
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Reale Abtastung
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
## Einleitung
Im Gegensatz zur [idealen Abtastung](GDET3%20Ideale%20Abtastung.ipynb) werden hier zwei Verfahren zur realen Abtastung betrachtet. Tatsächlich kann nicht mit einem idealen Dirac an einem definierten Zeitpunkt abgetastet werden. Im Folgenden werden zwei Verfahren der Abtastung, die *Shape-top Abtastung* und die *Flat-top Abtastung* beschrieben.
## Shape-top Abtastung
Bei der Shape-top Abtastung wird das kontinuierliche Signal $s(t)$ mit Abstand $T=\frac{1}{r}$ abgetastet.
Anstatt einer Diracfolge wird eine Folge schmaler Rechteckimpulse mit endlicher Dauer $T_0$ verwendet. Das abgetastete Signal $s_0(t)$ ergibt sich zu
$$
s_0(t)
= s(t) \cdot \sum\limits_{n=-\infty}^\infty \mathrm{rect}\left(\frac{t-nT}{T_0}\right)
= s(t) \cdot \left[\mathrm{rect}\left(\frac{t}{T_0}\right) \ast \sum\limits_{n=-\infty}^\infty \delta(t-nT) \right].
$$
Im Frequenzbereich folgt durch Transformation
$$
S_0(f)
= S(f) \ast \left[T_0 \mathrm{si}\left(\pi T_0 f\right) \cdot \frac{1}{T}\sum_{k=-\infty}^\infty \delta(f-kr)\right]
=
S(f) \ast \left[\frac{T_0}{T} \sum_{k=-\infty}^\infty \delta\left(f-\frac{k}{T}\right) \mathrm{si} \left(\pi T_0 \frac{k}{T}\right) \right]\text{.}
$$
Auch hier entstehen wie bei der idealen Abtastung spektrale Kopien, welche um $\frac{k}{T}$ zentriert sind. Jede spektrale Kopie wird mit einem von $f$ unabhängigen Faktor $\mathrm{si} \left(\pi T_0 \frac{k}{T}\right)$ skaliert.
Der Grenzübergang $T_0\rightarrow 0$ liefert hier die ideale Abtastung: $\lim\limits_{T_0\rightarrow 0}\left(\frac{1}{T_0}s_0(t)\right) = s_\mathrm{a}(t)$.
%% Cell type:markdown id: tags:
## Flat-top Abtastung
Bei der Flat-top Abtastung wird in Intervallen endlicher Dauer abgetastet und der Signalwert dann um $T=\frac{1}{r}$ gehalten. Dieses Verfahren wird häufig in Analog-Digital-Wandlern eingesetzt. Das abgetastete Signal $s_0(t)$ ergibt sich somit zu
$$
s_0(t)
= \sum\limits_{n=-\infty}^\infty s(nT) \mathrm{rect}\left(\frac{t}{T}-\frac{1}{2}-nT\right)
= s_\mathrm{a}(t) \ast \mathrm{rect}\left(\frac{t}{T}-\frac{1}{2}\right)
= \left[s(t) \cdot \sum\limits_{n=-\infty}^\infty \delta(t-nT)\right] \ast \mathrm{rect}\left(\frac{t}{T}\right)\ast \delta\left(t-\frac{T}{2}\right) \text{.}
$$
Im Frequenzbereich folgt dann
$$
S_0(f)
= S_\mathrm{a}(f) \cdot T \cdot \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-\mathrm{j}\pi f T}
= \left[S(f) \ast \sum\limits_{k=-\infty}^\infty \delta(f-kr)\right] \cdot \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-\mathrm{j}\pi f T}\text{.}
$$
In der Demonstration kann der Unterschied zwischen der Shape-top und der Flat-top Abtastung noch einmal anschaulich betrachtet werden.
%% Cell type:markdown id: tags:
## Beispiel
### Abtastung
Zunächst wird noch einmal die [ideale Abtastung](GDET3%20Ideale%20Abtastung.ipynb) wiederholt. In der Abbildung ist als gestrichelte Linie das Signal $s(t)$ dargestellt, das zugehörige Spektrum in blau. Das Signal wird mit Abtastrate $r=2$ abgetastet.
Das abgetastete Signal
$s_\mathrm{a}(t) = \sum\limits_{n=-\infty}^\infty s(nT)\cdot\delta(t-nT)$ und das Spektrum des abgetasteten Signals
$S_\mathrm{a}(f) = \frac{1}{T} \sum\limits_{k=-\infty}^\infty S(f-kr)$ sind ebenfalls abgebildet.
Das Spektrum des abgetasteten Signals zeigt die für die Abtastung typischen spektralen Wiederholungen.
%% Cell type:code id: tags:
``` python
# Construction of s(t) and corresponding spectrum S(f)
t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis
f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis
F = 0.9 # frequency of the signal
s = lambda t: signals_t['cos-Funktion'](t*F);
S = lambda f: signals_f['cos-Funktion'](f, F);
# Ideal sampling: Construction of sa(t) and Sa(f)
r = 2; T = 1/r; # sampling rate
## Time domain
nT, snT = rwth_transforms.sample(t, s(t), T)
## Frequency domain
Sa = np.zeros_like(S(f))
kMax = 16 # number of k values in sum for Sa(f), should be infinity :)
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
fSadirac = f[np.where(Sa)]; Sadirac = Sa[np.where(Sa)]
# Plot
## Time domain
fig, axs = plt.subplots(2,1, **rwth_plots.landscape)
ax = axs[0]; ax.set_title('Zeitbereich');
ax.plot(t, s(t), color='rwth:blue', linestyle='--', label=r'$s(t)$');
rwth_plots.plot_dirac(ax, nT, snT, 'rwth:red', label=r'$s_\mathrm{a}(t)$')
ax.set_xlabel(r'$\rightarrow t$'); ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
## Frequency domain
ax = axs[1]; ax.set_title('Frequenzbereich');
rwth_plots.plot_dirac(ax, fSadirac, Sadirac, 'rwth:red', label=r'$S_\mathrm{a}(f)$');
rwth_plots.plot_dirac(ax, f[np.where(S(f))], S(f)[np.where(S(f))], 'rwth:blue', label=r'$S(f)$');
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_xlabel(r'$\rightarrow f$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
txt,_=rwth_plots.annotate_xtick(ax, r'$r=2$', r, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);
```
%% Cell type:markdown id: tags:
Nun wird das abgetastete Signal $s_0(t)$ im Zeitbereich betrachtet, welches mittels Flat-top Abtastung erzeugt wurde:
$$
s_0(t)
= s_\mathrm{a}(t) \ast \mathrm{rect}\left(\frac{t}{T}-\frac{1}{2}\right)
= \sum\limits_{n=-\infty}^\infty s(nT) \mathrm{rect}\left(\frac{t}{T}-\frac{1}{2}-nT\right).
$$
Die Abtastrate ist ebenfalls $r=2$.
Für die Flat-top Abtastung charakteristisch wird der Signalwert bis zum nächsten Abtastwert gehalten.
%% Cell type:code id: tags:
``` python
# Time-Domain
s0 = np.zeros_like(t) # sum of rects
Nmax = np.ceil(t[-1]/T) # Parts of the infinite rect sum, should be infinity :)
for n in np.arange(-Nmax,Nmax+1):
s0 = s0 + rect((t-n*T)/T-0.5) * s(n*T)
# Plot
fig, ax = plt.subplots(**rwth_plots.landscape); ax.set_title('Zeitbereich')
ax.plot(t, s(t), 'rwth:blue', linestyle='--', label=r'$s(t)$'); ax.plot(t, s0, 'rwth:red', label=r'$s_0(t)$')
ax.set_xlabel(r'$\rightarrow t$'); ax.set_xlim([-2.9, 2.9]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Dies hat im Frequenzbereich zur Konsequenz, dass die spektralen Kopien mit $T \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-j\pi f T}$ gewichtet werden.
$S_0(f)$ ergibt sich also zu
$$
S_0(f)
= S_\mathrm{a}(f) \cdot T \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-j\pi f T}.
$$
Die nachfolgende Abbildung verdeutlicht diesen Effekt.
%% Cell type:code id: tags:
``` python
# Frequency domain
S_si = T*si(np.pi*T*f)
S_exp = np.exp(-1j*np.pi*f*T)
S0 = Sa * S_si * S_exp
# Plot
## Magnitude
fig, axs = plt.subplots(2,1, **rwth_plots.landscape);
ax = axs[0]; ax.set_title('Betrag')
ax.plot(f, np.abs(S_si*S_exp), 'k--', label=r'$|T\mathrm{si}(\pi f T)e^{-\mathrm{j}\pi f T}|$')
fS0dirac = f[np.where(S0)]; S0dirac = S0[np.where(S0)] # sample S0 and f
rwth_plots.plot_dirac(ax, fS0dirac, np.abs(S0dirac), 'rwth:red', label=r'$|S_0(f)$|');
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_xlabel(r'$\rightarrow f$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
## Phase
ax = axs[1]; ax.set_title('Phase')
ax.plot(f, np.angle(S_si*S_exp), 'k--', label=r'$\angle T\mathrm{si}(\pi f T)e^{-\mathrm{j}\pi f T}$')
rwth_plots.stem(ax, fS0dirac, np.angle(S0dirac), 'rwth:red', label=r'$\angle S_0(f)$')
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_xlabel(r'$\rightarrow f$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
### Rekonstruktion
Durch die Multiplikation von $S_\mathrm{a}(f)$ mit $T \cdot \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-j\pi f T}$ wird das Spektrum $S_0(f)$ im Basisband verzerrt. So ist es nicht möglich, $S(f)$ mittels eines einfachen idealen Tiefpasses zu rekonstruieren. Zusätzlich ist ein Filter nötig, welches diesen Faktor ausgleicht, dieses ist in der folgenden Abbildung dargestellt.
$$
H_\mathrm{eq}(f) = \frac{1}{T \cdot \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-j\pi f T}}
$$
%% Cell type:code id: tags:
``` python
# Reconstruction filters #plt.close('all')
## Ideal Low pass to crop the base band
H_lp = rect(f/(r+0.001)) # ideal low pass between -r/2 and r/2
## Equalizing filter to compensate the influence of si(...) and exp(...) terms in S_0(f)
H_eq = 1/(T*si(np.pi*T*f) * np.exp(-1j*np.pi*f*T))
## Overall reconstruction filter
H = H_lp * H_eq
# Plot
fig,axs = plt.subplots(2,1, **rwth_plots.landscape)
ax = axs[0]
ax.plot(f, np.abs(H_eq), 'k--', linewidth=1, label=r'$|H_\mathrm{eq}(f)|$')
ax.plot(f, np.abs(H), 'k', label=r'$|H(f)|$')
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_ylim([-.1,21]);
ax.set_xlabel(r'$\rightarrow f$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
ax = axs[1]
ax.plot(f, np.angle(H_eq), 'k--', linewidth=1, label=r'$\angle H_\mathrm{eq}(f)$')
ax.plot(f, np.angle(H)*H_lp, 'k', label=r'$\angle H(f)$')
ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); #ax.set_ylim([-.1,11]);
ax.set_xlabel(r'$\rightarrow f$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Dieses Filter wird nun zur Rekonstruktion angewendet.
Das rekonstruierte Signal unter Verwendung des ausgleichenden Filters ist unten abgebildet. Das Originalsignal konnte erfolgreich rekonstruiert werden.
%% Cell type:code id: tags:
``` python
G = S0 * H*T;
g = rwth_transforms.idft(G); g = np.fft.ifftshift(np.real(g)); # IDFT
G = np.real(G); # discards small imaginary numbers close to zero
# Plot
fig, axs = plt.subplots(2, 1, **rwth_plots.landscape)
ax = axs[0]; fGdirac = f[np.where(G)]; Gdirac = G[np.where(G)]
rwth_plots.plot_dirac(ax, fGdirac, Gdirac, 'rwth:green');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow G(f)$', bbox=rwth_plots.wbbox);
ax.set_xlim([-7.5,7.5]); rwth_plots.grid(ax); rwth_plots.axis(ax);
ax = axs[1]; ax.plot(t, s(t), color='rwth:blue', linestyle='--', label=r'$s(t)$');
ax.plot(t/deltat/(f[-1]*2), g, color='rwth:green', linestyle='-', label=r'$g(t)$');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
## Demo
In der folgenden interaktiven Demonstration kann nun betrachtet werden, was der Unterschied zwischen der Flat-top und der Shape-top Abtastung ist.
Dargestellt sind untereinander:
* der Zeitbereich mit dem Originalsignal und dem abgestasteten Signal
* der zugehörige Frequenzbereich mit dem Originalspektrum, dem Spektrum des abgetasteten Signal und dem Rekonstruktionsfilter
* das rekonstruierte Spektrum
* das rekonstruierte Signal im Zeitbereich.
Im Drop-Down-Menü kann die Art der Abtastung (Shape-top oder Flat-top) sowie die abzutastende Funktion (Cosinus-, Sinus-und si-Funktion, sowie Rechteck- oder Dreieckimpuls) ausgewählt werden.
Über den Schieberegler kann $F$ geändert werden, was bei Cosinus-, Sinus- und si-Funktion die Frequenz und bei Rechteck- und Dreieckimpuls die Breite beeinflusst.
%% Cell type:code id: tags:
``` python
T0 = T/4 # width of rects for shape-top sampling
fig, axs = plt.subplots(4, 1, **rwth_plots.landscape); plt.tight_layout();
@widgets.interact(sampling_type=widgets.Dropdown(options=['Shape-top', 'Flat-top'], description=r'Art der Abtastung:', style=rwth_plots.wdgtl_style),
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=rwth_plots.wdgtl_style, continuous_update=False))
def update_plots(sampling_type, s_type, F):
s = lambda t: signals_t[s_type](t*F);
S = lambda f: signals_f[s_type](f, F);
nT, snT = rwth_transforms.sample(t, s(t), T)
# Construct sampled signal
if sampling_type == 'Shape-top':
u = np.zeros_like(t) # sum of rects
for n in np.arange(-Nmax,Nmax+1):
u = u + rect((t-n*T)/T0)
s0 = s(t) * u
elif sampling_type == 'Flat-top':
s0 = np.zeros_like(t) # sum of rects
for n in np.arange(-Nmax,Nmax+1):
s0 = s0 + rect((t-n*T)/T-0.5) * s(n*T)
# Construct sampled spectrum
if sampling_type == 'Shape-top':
S0 = np.zeros_like(S(f))
for k in np.arange(-kMax, kMax+1): # evaluate infinite sum only for 2*kMax+1 elements
S0 += S(f-k/T) * si(np.pi*T0*k/T)
S0 = S0*T0/T
elif sampling_type == 'Flat-top':
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)
S0 = Sa * si(np.pi*T*f) * np.exp(-1j*np.pi*f*T)
# Reconstruct g(t)
if sampling_type == 'Shape-top':
H = H_lp
G = S0 * H * T / T0;
elif sampling_type == 'Flat-top':
H = H_lp * H_eq * T
G = S0 * H
g = rwth_transforms.idft(G);
g = np.fft.ifftshift(np.real(g)); # IDFT
# Sample for plot
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
fS0dirac = f[np.where(S0)]; S0dirac = S0[np.where(S0)]
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':
Sdirac = np.imag(Sdirac); S = lambda f: np.imag(signals_f[s_type](f, F));
G = np.imag(G); Gdirac = np.imag(Gdirac)
else:
Sdirac = np.real(Sdirac); S0 = np.real(S0); G = np.real(G); Gdirac = np.real(Gdirac)
else:
g /= (len(f)/(2*f[-1])) # Parseval :)
S0dirac = np.zeros_like(f)
G = np.real(G)
if sampling_type == 'Shape-top': # normalize to T0 for plotting reasons
S0 = S0/T0
S0dirac = S0dirac/T0
# 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), 'rwth:blue', linestyle='--', label=r'$s(t)$');
ax.plot(t, s0, 'rwth:red', label=r'$s_0(t)$')
ax.set_xlabel(r'$\rightarrow t$');
ax.set_xlim([-2.9, 2.9]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
ax = axs[1]; ax.set_title('Frequenzbereich');
ax.plot(f, np.abs(H), '-', color='rwth:black', label=r'$|H(f)|$')
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ax.plot(f, np.ones_like(f)*np.nan, '-', color='rwth:red', label=r'$|S_0(f)|$');
rwth_plots.plot_dirac(ax, fS0dirac, np.abs(S0dirac), 'rwth:red');
else:
ax.plot(f, np.abs(S0), '-', color='rwth:red', label=r'$|S_0(f)|$');
rwth_plots.plot_dirac(ax, [], [], 'rwth:red');
ax.plot(f, S(f), color='rwth:blue', 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$'); rwth_plots.grid(ax); rwth_plots.axis(ax);
txt,_=rwth_plots.annotate_xtick(ax, r'$r=2$', r, -.15, 'rwth:black'); txt.get_bbox_patch().set_alpha(1);
txt,_=rwth_plots.annotate_xtick(ax, r'$f_\mathrm{g}$', r/2, -.15, 'rwth: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='rwth:green');
rwth_plots.plot_dirac(ax, fGdirac, Gdirac, 'rwth:green');
else:
ax.plot(f, G, '-', color='rwth:green');
rwth_plots.plot_dirac(ax, [], [], 'rwth:red');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow G(f)$', bbox=rwth_plots.wbbox);
ax.set_xlim([-7.5,7.5]); rwth_plots.grid(ax); rwth_plots.axis(ax);
ax = axs[3]; ax.set_title('Zeitbereich (nach Rekonstruktion)');
ax.plot(t, s(t), color='rwth:blue', linestyle='--', label=r'$s(t)$');
ax.plot(t/deltat/(f[-1]*2), g, 'rwth:green', label=r'$g(t)$');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); rwth_plots.grid(ax); rwth_plots.axis(ax);
plt.tight_layout()
else:
axs[0].lines[0].set_ydata(s(t)); axs[0].lines[1].set_ydata(s0); axs[1].lines[-3].set_ydata(S(f));
axs[1].lines[0].set_ydata(np.abs(H))
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': # dirac plot
rwth_plots.dirac_set_data(axs[1].containers, fS0dirac, np.abs(S0dirac));
axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan);
rwth_plots.dirac_set_data(axs[2].containers, fGdirac, Gdirac); axs[2].lines[0].set_ydata(np.ones_like(f)*np.nan);
else:
axs[1].lines[1].set_ydata(np.abs(S0)); rwth_plots.dirac_set_data(axs[1].containers, [], []);
axs[2].lines[0].set_ydata(G); rwth_plots.dirac_set_data(axs[2].containers, [], []);
axs[3].lines[0].set_ydata(s(t)); axs[3].lines[1].set_ydata(g);
if s_type == 'sin-Funktion': # Adapt labels
axs[1].lines[-3].set_label(r'$\mathrm{Im}\{S(f)\}$');
axs[2].yaxis.label.set_text(r'$\uparrow \mathrm{Im}\{G(f)\}$');
else:
axs[1].lines[-3].set_label(r'$S(f)$')
axs[2].yaxis.label.set_text(r'$\uparrow G(f)$');
axs[1].legend(loc=2)
tmp = np.concatenate((np.abs(S0),np.abs(S0dirac),np.abs(H))); rwth_plots.update_ylim(axs[1], tmp, 0.19, np.max(np.abs(tmp))); rwth_plots.update_ylim(axs[2], G, 0.19, np.max(G));
rwth_plots.update_ylim(axs[3], np.concatenate((s(t),g)), 0.19, np.max(np.concatenate((s(t),g))));
```
%% Cell type:markdown id: tags:
### Aufgaben
Wähle eine beliebige Funktion aus.
* Wie sieht das abgetastete Signal mit Shape-top Abtastung aus und wie mit Flat-top Abtastung?
* Welche Auswirkungen hat die Abtastungsart auf das Spektrum und die Rekonstruktion?
* Variiere $F$. Was passiert?
* Führe diese Beobachtung für unterschiedliche Funktionen aus.
%% 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.
......
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