Commit 1bb3ab2d authored by Hafiz Emin Kosar's avatar Hafiz Emin Kosar
Browse files

- using ient_landscape in Abtastung notebooks

parent 4aa5ef6f
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University # Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget %matplotlib widget
from ipywidgets import interact, interactive, fixed, HBox, VBox from ipywidgets import interact, interactive, fixed, HBox, VBox
import ipywidgets as widgets import ipywidgets as widgets
from IPython.display import clear_output, display, HTML from IPython.display import clear_output, display, HTML
from src.sampling.sampling_plot import SamplingPlot from src.sampling.sampling_plot import SamplingPlot
from ient_nb.ient_plots import * from ient_nb.ient_plots import *
from ient_nb.ient_transforms import * from ient_nb.ient_transforms import *
from ient_nb.ient_signals import * from ient_nb.ient_signals import *
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<div> <div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;"> <img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div> </div>
# Ideale Abtastung # Ideale Abtastung
Dieses Notebook soll die ideale Abtastung veranschaulichen. Dieses Notebook soll die ideale Abtastung veranschaulichen.
![Blockdiagramm](figures/sampling_block_diagram.png) ![Blockdiagramm](figures/sampling_block_diagram.png)
Das zeitkontinuierliche Signal $s(t)$ wird zu Zeitpunkten $nT$ mit Abtastperiode $T$ abgetastet. Das resultierende, ideal abgetastete Signal 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)$$ $$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: 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{.}$$ $$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. 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 die spektrale Kopie bei $k=0$ (auch Basisband genannt) aus $S_\mathrm{a}(f)$ rekonstruieren soll. 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 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. $$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 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{.}$$ $$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. Das rekonstuierte Signal im Zeitbereich $g(t)$ wird dann durch Rücktransformation gewonnen.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Demo ## 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. 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. 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) = \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) = \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{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) = \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)$. * $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! 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. 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. 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)$. 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: %% Cell type:code id: tags:
``` python ``` python
r = 2; T = 1/r; # sampling frequency r = 2; T = 1/r; # sampling frequency
signals_t = {'cos-Funktion': lambda t: np.cos(2 * np.pi * t), signals_t = {'cos-Funktion': lambda t: np.cos(2 * np.pi * t),
'sin-Funktion': lambda t: np.sin(2 * np.pi * t), 'sin-Funktion': lambda t: np.sin(2 * np.pi * t),
'si-Funktion': lambda t: si(2 * np.pi * t), 'si-Funktion': lambda t: si(2 * np.pi * t),
'Rechteckimpuls': lambda t: rect(t / 1.05), 'Rechteckimpuls': lambda t: rect(t / 1.05),
'Dreieckimpuls': tri} 'Dreieckimpuls': tri}
signals_f = {'cos-Funktion': lambda f, F: np.isin(f/F, f[findIndOfLeastDiff(f/F, [-1, 1])]/F) * 0.5, 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, '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)), '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), '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} 'Dreieckimpuls': lambda f, F: 1/np.abs(F)*si(np.pi * f/F) ** 2}
#f = t; #f = t;
t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis
f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis
kMax = 16 # number of k values in sum for Sa(f) kMax = 16 # number of k values in sum for Sa(f)
# Plot # Plot
plt.close(); fig, axs = plt.subplots(4, 1); fig.canvas.layout.height = '800px'; plt.tight_layout(); plt.close(); fig, axs = plt.subplots(4, 1, **ient_landscape); plt.tight_layout();
@widgets.interact(s_type=widgets.Dropdown(options=list(signals_t.keys()), description=r'Wähle $s(t)$:'), @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, continuous_update=False)) 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): def update_plots(s_type, F):
s = lambda t: signals_t[s_type](t*F); s = lambda t: signals_t[s_type](t*F);
S = lambda f: signals_f[s_type](f, F); S = lambda f: signals_f[s_type](f, F);
nT, snT = ient_sample(t, s(t), T) nT, snT = ient_sample(t, s(t), T)
# Construct sampled spectrum # Construct sampled spectrum
Sa = np.zeros_like(S(f)) Sa = np.zeros_like(S(f))
for k in np.arange(-kMax, kMax+1): # evaluate infinite sum only for 2*kMax+1 elements for k in np.arange(-kMax, kMax+1): # evaluate infinite sum only for 2*kMax+1 elements
Sa += S(f-k/T) Sa += S(f-k/T)
Sa = Sa/T Sa = Sa/T
# Reconstruct g(t) # Reconstruct g(t)
H_lp = rect(f/(r+0.001)) # reconstruction filter H_lp = rect(f/(r+0.001)) # reconstruction filter
G = Sa * H_lp * T; # reconstruction G = Sa * H_lp * T; # reconstruction
g = ient_idft(G); g = ient_idft(G);
g = np.fft.ifftshift(np.real(g)); # IDFT g = np.fft.ifftshift(np.real(g)); # IDFT
# Sample # Sample
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
fSadirac = f[np.where(Sa)]; Sadirac = Sa[np.where(Sa)] fSadirac = f[np.where(Sa)]; Sadirac = Sa[np.where(Sa)]
fSdirac = f[np.where(S(f))]; Sdirac = S(f)[np.where(S(f))] fSdirac = f[np.where(S(f))]; Sdirac = S(f)[np.where(S(f))]
fGdirac = f[np.where(G)]; Gdirac = G[np.where(G)] fGdirac = f[np.where(G)]; Gdirac = G[np.where(G)]
if s_type == 'sin-Funktion': 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) 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: else:
g /= (len(f)/(2*f[-1])) # Parseval :) g /= (len(f)/(2*f[-1])) # Parseval :)
# Plot # Plot
if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time 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 = axs[0]; ax.set_title('Zeitbereich');
ax.plot(t, s(t), color='rwth', linestyle='--', label=r'$s(t)$'); 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)$') ient_plot_dirac(ax, nT, snT, 'rot', label=r'$s_\mathrm{a}(t)$')
ax.set_xlabel(r'$\rightarrow 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.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);
ax = axs[1]; ax.set_title('Frequenzbereich'); ax = axs[1]; ax.set_title('Frequenzbereich');
ax.plot(f, H_lp, '-', color='black', label=r'$H_\mathrm{TP}(f)$') ax.plot(f, H_lp, '-', color='black', label=r'$H_\mathrm{TP}(f)$')
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': 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)$'); ax.plot(f, np.ones_like(f)*np.nan, '-', color='rot', label=r'$S_a(f)$');
ient_plot_dirac(ax, fSadirac, Sadirac, 'rot'); ient_plot_dirac(ax, fSadirac, Sadirac, 'rot');
else: else:
ax.plot(f, Sa, '-', color='rot', label=r'$S_a(f)$'); ax.plot(f, Sa, '-', color='rot', label=r'$S_a(f)$');
ient_plot_dirac(ax, [], [], 'rot'); ient_plot_dirac(ax, [], [], 'rot');
ax.plot(f, S(f), color='rwth', linestyle='--', linewidth=1, label=r'$S(f)$') 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_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); ax.set_xlabel(r'$\rightarrow f$'); ient_grid(ax); ient_axis(ax);
txt,_=ient_annotate_xtick(ax, r'$r=2$', r, -.15, '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); txt,_=ient_annotate_xtick(ax, r'$f_\mathrm{g}$', r/2, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);
ax = axs[2]; ax = axs[2];
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':
ax.plot(f, np.ones_like(f)*np.nan, '-', color='grun'); ax.plot(f, np.ones_like(f)*np.nan, '-', color='grun');
ient_plot_dirac(ax, fGdirac, Gdirac, 'grun'); ient_plot_dirac(ax, fGdirac, Gdirac, 'grun');
else: else:
ax.plot(f, G, '-', color='grun'); ax.plot(f, G, '-', color='grun');
ient_plot_dirac(ax, [], [], 'rot'); ient_plot_dirac(ax, [], [], 'rot');
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=ient_wbbox); 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=ient_wbbox);
ax.set_xlim([-7.5,7.5]); ient_grid(ax); ient_axis(ax); ax.set_xlim([-7.5,7.5]); ient_grid(ax); ient_axis(ax);
ax = axs[3]; 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, s(t), color='rwth', linestyle='--', label=r'$s(t)$');
ax.plot(t/deltat/(f[-1]*2), g, 'grun', label=r'$g(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); 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() plt.tight_layout()
else: else:
axs[0].lines[0].set_ydata(s(t)); axs[1].lines[-3].set_ydata(S(f)); axs[0].lines[0].set_ydata(s(t)); axs[1].lines[-3].set_ydata(S(f));
ient_dirac_set_data(axs[0].containers, nT, snT) ient_dirac_set_data(axs[0].containers, nT, snT)
if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': # dirac plot if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': # dirac plot
ient_dirac_set_data(axs[1].containers, fSadirac, Sadirac); axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan); ient_dirac_set_data(axs[1].containers, fSadirac, Sadirac); axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan);
ient_dirac_set_data(axs[2].containers, fGdirac, Gdirac); axs[2].lines[0].set_ydata(np.ones_like(f)*np.nan); ient_dirac_set_data(axs[2].containers, fGdirac, Gdirac); axs[2].lines[0].set_ydata(np.ones_like(f)*np.nan);
else: else:
axs[1].lines[1].set_ydata(Sa); ient_dirac_set_data(axs[1].containers, [], []); axs[1].lines[1].set_ydata(Sa); ient_dirac_set_data(axs[1].containers, [], []);
axs[2].lines[0].set_ydata(G); ient_dirac_set_data(axs[2].containers, [], []); axs[2].lines[0].set_ydata(G); ient_dirac_set_data(axs[2].containers, [], []);
axs[3].lines[0].set_ydata(s(t)); axs[3].lines[1].set_ydata(g); axs[3].lines[0].set_ydata(s(t)); axs[3].lines[1].set_ydata(g);
if s_type == 'sin-Funktion': # Adapt labels 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[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\}$'); axs[2].yaxis.label.set_text(r'$\uparrow \mathrm{Im}\{G(f)=S_\mathrm{a}(f) \cdot H_\mathrm{TP}(f) \cdot T\}$');
else: else:
axs[1].lines[1].set_label(r'$S_\mathrm{a}(f)$'); axs[1].lines[-3].set_label(r'$S(f)$') 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[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) axs[1].legend(loc=2)
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[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)))); ient_update_ylim(axs[3], np.concatenate((s(t),g)), 0.19, np.max(np.concatenate((s(t),g))));
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Aufgaben ## 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? * 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? * 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$? * 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? * 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? * 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? * 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? * 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? * 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. 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? * 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? * 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? * 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? * Führe dieselben Überlegungen für den Dreiecksimpuls aus. Wie erklärt sich das unterschiedliche Verhalten?
%% Cell type:markdown id: tags: %% 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). 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: 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. *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: %% Cell type:code id: tags:
``` python ``` python
# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University # Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget %matplotlib widget
from ipywidgets import interact, interactive, fixed, HBox, VBox from ipywidgets import interact, interactive, fixed, HBox, VBox
import ipywidgets as widgets import ipywidgets as widgets
from IPython.display import clear_output, display, HTML from IPython.display import clear_output, display, HTML
from ient_nb.ient_plots import * from ient_nb.ient_plots import *
from ient_nb.ient_transforms import * from ient_nb.ient_transforms import *
from ient_nb.ient_signals import * from ient_nb.ient_signals import *
signals_t = {'cos-Funktion': lambda t: np.cos(2 * np.pi * t), signals_t = {'cos-Funktion': lambda t: np.cos(2 * np.pi * t),
'sin-Funktion': lambda t: np.sin(2 * np.pi * t), 'sin-Funktion': lambda t: np.sin(2 * np.pi * t),
'si-Funktion': lambda t: si(2 * np.pi * t), 'si-Funktion': lambda t: si(2 * np.pi * t),
'Rechteckimpuls': lambda t: rect(t / 1.05), 'Rechteckimpuls': lambda t: rect(t / 1.05),
'Dreieckimpuls': tri} 'Dreieckimpuls': tri}
signals_f = {'cos-Funktion': lambda f, F: np.isin(f/F, f[findIndOfLeastDiff(f/F, [-1, 1])]/F) * 0.5, 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, '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)), '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), '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} 'Dreieckimpuls': lambda f, F: 1/np.abs(F)*si(np.pi * f/F) ** 2}
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<div> <div>
<img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;"> <img src="ient_nb/figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div> </div>
# Reale Abtastung # Reale Abtastung
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. 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 ## Shape-top Abtastung
Bei der Shape-top Abtastung wird das kontinuierliche Signal $s(t)$ mit Abstand $T=\frac{1}{r}$ abgetastet. 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 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_0(t)
= s(t) \cdot \sum\limits_{n=-\infty}^\infty \mathrm{rect}\left(\frac{t-nT}{T_0}\right) = 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]. = 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 Im Frequenzbereich folgt durch Transformation
$$ $$
S_0(f) 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[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{.} 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. 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)$. 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: %% Cell type:markdown id: tags:
## Flat-top Abtastung ## 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 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) s_0(t)
= \sum\limits_{n=-\infty}^\infty s(nT) \mathrm{rect}\left(\frac{t}{T}-\frac{1}{2}-nT\right) = \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) = 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{.} = \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 Im Frequenzbereich folgt dann
$$ $$
S_0(f) S_0(f)
= S_\mathrm{a}(f) \cdot T \cdot \mathrm{si}(\pi f T) \cdot \mathrm{e}^{-\mathrm{j}\pi f T} = 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{.} = \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 nocheinmal anschaulich betrachtet werden. In der Demonstration kann der Unterschied zwischen der Shape-top und der Flat-top Abtastung nocheinmal anschaulich betrachtet werden.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Beispiel ## Beispiel
### Abtastung ### Abtastung
Zunächst wird nocheinmal 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. Zunächst wird nocheinmal 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 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}(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. $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. Das Spektrum des abgetasteten Signals zeigt die für die Abtastung typischen spektralen Wiederholungen.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# Construction of s(t) and corresponding spectrum S(f) # Construction of s(t) and corresponding spectrum S(f)
t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis
f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis
F = 0.9 # frequency of the signal F = 0.9 # frequency of the signal
s = lambda t: signals_t['cos-Funktion'](t*F); s = lambda t: signals_t['cos-Funktion'](t*F);
S = lambda f: signals_f['cos-Funktion'](f, F); S = lambda f: signals_f['cos-Funktion'](f, F);
# Ideal sampling: Construction of sa(t) and Sa(f) # Ideal sampling: Construction of sa(t) and Sa(f)
r = 2; T = 1/r; # sampling rate r = 2; T = 1/r; # sampling rate
## Time domain ## Time domain
nT, snT = ient_sample(t, s(t), T) nT, snT = ient_sample(t, s(t), T)
## Frequency domain ## Frequency domain
Sa = np.zeros_like(S(f)) Sa = np.zeros_like(S(f))
kMax = 16 # number of k values in sum for Sa(f), should be infinity :) 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 for k in np.arange(-