Commit 77b00bb6 authored by Hafiz Emin Kosar's avatar Hafiz Emin Kosar
Browse files

- typos

parent 3f0aad80
%% 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
import matplotlib.pyplot as plt
import numpy as np
import rwth_nb.plots.mpl_decorations as rwth_plots
from rwth_nb.misc.signals import *
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Fourier-Reihenkoeffizienten
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:markdown id: tags:
## Einleitung
Im Folgenden soll die periodische Rechteckfunktion
$$s_\mathrm{p}(t) =
\mathrm{rect}\left(\frac{t}{T_1}\right) \ast
\sum_{n=-\infty}^\infty \delta(t-nT)
$$
durch eine *endliche* Fourier-Summe $s_{\mathrm{p},N}(t)$ approximiert werden.
%% Cell type:code id: tags:
``` python
t = np.linspace(-3,3,10000) # t-axis
T = 1; F = 1/T; # periodicity T
T1 = T/2
# Parts of the infinite rect sum
Nmax = 3 # should be infinity :-)
s = np.zeros_like(t)
for n in np.arange(-Nmax,Nmax+1):
s = s + rect((t-n)/T1)
# Plot
fig,ax = plt.subplots(figsize=(6,3)); ax.plot(t, s, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s_{\mathrm{p}}(t)$');
ax.set_xlim([-2.9, 2.9]); ax.set_ylim([0, 1.09]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Die zugehörigen Fourier-Reihenkoeffizienten lassen sich (wie im Buch) berechnen zu
$$
S_\mathrm{p}(k)
=
\frac{\sin\left(k\pi\frac{T_1}{T}\right)}{k\pi}\quad\text{mit }k\neq 0
$$
und
$$
S_\mathrm{p}(k=0) = \frac{T_1}{T}\text{.}
$$
Im Folgenden ist $T=\frac{1}{F} = 1$.
Im Zeitbereich kann die Fourier-Summe durch eine endliche Summe (Summation bis zu $\pm N$ anstelle $\pm \infty$) wie folgt angenähert werden:
$$
s_{\mathrm{p},N}(t)
=
\sum_{k=-N}^N S_\mathrm{p}(k) \mathrm{e}^{\mathrm{j} 2 \pi k F t}
\text{ .}
$$
Da $s_\mathrm{p}(t)$ hier ein reelles Signal ist (und damit $S_\mathrm{p}(-k) = S_\mathrm{p}^\ast(k)$ gilt), kann es somit über den Gleichanteil und die Fourier-Koeffizienten durch
$$
s_{\mathrm{p},N}(t)
=
S_\mathrm{p}(0) + 2 \sum_{k=1}^N \mathrm{Re}\left\{ S_\mathrm{p}(k) \mathrm{e}^{\mathrm{j} 2 \pi k F t} \right\}
$$
beschrieben werden.
Zunächst für ein einfaches Beispiel mit $N=4$:
%% Cell type:code id: tags:
``` python
N = 4
k = np.arange(0,N)
# Fourier series coefficients
Sp = np.zeros(N)
Sp[0] = T1/T # k=0
Sp[1::] = np.sin(k[1::]*np.pi*T1/T)/(k[1::]*np.pi) # k > 0
# Plot
fig,ax = plt.subplots(); rwth_plots.stem(ax, k, Sp, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow k$'); ax.set_ylabel(r'$\uparrow S_{\mathrm{P}}(k)$'); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Abgebildet sind die Koeffizienten $Sp_p(k)$ für $k=0,...,3$. Aus diesen vier Koeffizienten wird nun das Ursprungssignal angenähert.
Abgebildet sind die Koeffizienten $S_p(k)$ für $k=0,...,3$. Aus diesen vier Koeffizienten wird nun das Ursprungssignal angenähert.
Die folgende Abbildung zeigt die einzelnen Summanden
$
2 \mathrm{Re}\left\{ S_\mathrm{p}(k) \mathrm{e}^{\mathrm{j} 2 \pi k F t} \right\}
$
sowie das Resultat $s_{\mathrm{p},N}(t)$:
%% Cell type:code id: tags:
``` python
# Approximated time signal
sp = Sp[0]*np.ones_like(t) # DC
fig,axs = plt.subplots(2,1); colors = ['rwth:green', 'rwth:magenta', 'rwth:orange']; ax = axs[0];
ax.plot(t,sp, 'rwth:blue-50', linestyle='--', label=r'$S_\mathrm{p}(0)$')
legend = np.array([r'$k==0$'])
for kIter in k[1::]:
spIter = 2*np.real(Sp[kIter]*np.exp(2j*np.pi*kIter*F*t));
sp = sp + spIter;
# Plot
ax.plot(t,spIter, color=colors[kIter-1], linestyle='--', label=r'$k={}$'.format(kIter))
ax.set_xlabel(r'$\rightarrow t$'); ax.legend(loc='lower left');
ax.set_xlim([-1.6,1.6]); ax.set_ylim([-1.1,1.1]); rwth_plots.axis(ax);
ax = axs[1]; ax.plot(t, sp)
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s_{\mathrm{P},N}(t)$');
ax.set_xlim([-1.6,1.6]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Die verwendeten Koeffizienten erzeugen Signalanteile mit ansteigender Frequenz.
Obwohl für die Rekonstruktion nur vier Koeffizienten verwendet wurden, ist die Annäherung an das ursprüngliche Rechtecksignal zu erkennen. Für eine klarere Darstellung der Ecken im Signal fehlen die hochfrequenten Anteil der höheren Koeffizienten. In der folgenden Demonstration kann dieser Effekt anschaulich betrachtet werden.
%% Cell type:markdown id: tags:
## Demo
Die Demonstration ermöglicht die Untersuchung des Einflusses der Anzahl der zur Rekonstruktion verwendeten Koeffizienten $N$ und der Breite $T_1$ des verwendeten Rechtecks.
Über den Slider können verschiedene Werte für $N$ und $T_1$ eingestellt werden. Die gestrichelte schwarze Linie in der oberen Abbildung zeigt das zu approximierende Ausgangssignal, die blaue Linie die errechnete Annäherung unter Verwendung von $N$ Koeffizienten. Die verwendeten Koeffizienten sind in der unteren Abbildung dargestellt.
%% Cell type:code id: tags:
``` python
fig,axs = plt.subplots(2,1);
@widgets.interact(N=widgets.IntSlider(min=1, max=50, step=1, description='$N$', continuous_update=False),
T1=widgets.FloatSlider(min=0.125, max=.75, step=0.125, value=.5, description='$T_1$',
continuous_update=False, readout_format='.3f',))
def update_plot(N, T1):
# Snippet of time signal
s = np.zeros_like(t)
for n in np.arange(-Nmax,Nmax+1):
s = s + rect((t-n)/T1)
# Fourier series coefficients
k = np.arange(0,N)
Sp = np.zeros(N)
Sp[0] = T1/T
Sp[1::] = np.sin(k[1::]*np.pi*T1/T)/(k[1::]*np.pi)
# Approximated time signal
sp = Sp[0]*np.ones_like(t) # DC
for kIter in k[1::]:
sp = sp + 2*np.real(Sp[kIter]*np.exp(2j*np.pi*kIter*F*t));
k = np.concatenate((-k[::-1],k[1::]));
Sp = np.concatenate((Sp[::-1],Sp[1::]))
# Plot
if not axs[0].lines: # create plot
ax = axs[0]; ax.plot(t, s, 'k--')
ax.plot(t, sp, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s_{\mathrm{P},N}(t)$');
ax.set_xlim([-1.6,1.6]); ax.set_ylim([-.2, 1.2]); rwth_plots.axis(ax);
ax = axs[1]; rwth_plots.stem(ax, k, Sp, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow k$'); ax.set_ylabel(r'$\uparrow S_{\mathrm{P}}(k)$');
rwth_plots.axis(ax); ax.set_ylim([-.29,.89])
else: # update plot
axs[0].lines[0].set_ydata(s); axs[0].lines[1].set_ydata(sp);
rwth_plots.stem_set_data(axs[1].containers[0], k, Sp);plt.show()
axs[1].set_xlim([-N+.5, N-.5])
```
%% Cell type:markdown id: tags:
## Aufgaben
* Variiere $N$ und halte $T_1=0.5$ konstant. Wieviele Koeffizienten erhält man für $N=10$ und wie sind diese angeordnet? Warum?
* Ab welchem $N$ ist annähernd die Struktur des Ausgangssignals zu erkennen?
* Setze $N=50$. Wie verhält sich das rekonstruierte Signal an den Ecken des Rechteckimpulses? Warum?
* Variiere nun $T_1$. Setze $N=7$ und beobachte, was mit den Koeffizienten passiert, wenn $T_1$ kleine oder große Werte annimmt. Was passiert mit dem approximierten Signal?
* Für welche Kombination der Werte $N$ und $T_1$ kann die angenäherte Stuktur des Ausgangssignal erkannt werden? Warum?
%% Cell type:markdown id: tags:
---
This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT).
Please attribute the work as follows:
*Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2020, [Institut für Nachrichtentechnik](http://www.ient.rwth-aachen.de), 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 *
```
%% 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 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 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 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 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
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
from rwth_nb.misc.signals import *
import rwth_nb.misc.transforms as rwth_transforms
def convolution(s, h):
# Convolve s and h numerically
return signal.convolve(s(t), h(t), mode='same')*deltat
(t,deltat) = np.linspace(-20, 20, 50001, retstep=True) # t Achse
(f,deltaf) = np.linspace(-20, 20, 50001, retstep=True) # f Achse
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Übertragungsfunktion
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
## Einleitung
In diesem Beispiel wird die Übertragung eines Eingangssignal $s(t)$ über ein System mit der Impulsantwort $h(t)$ und der zugehörigen Übertragungsfunktion $H(f)$ gezeigt.
## Eingangssignal
Das verwendete Eingangssignal ist ein Rechteck mit der Breite $T_0=4$:
$\displaystyle s(t) = \frac{1}{T_0}\mathrm{rect}\left(\frac{t}{T_0}\right)$. Dieses ist in der folgenden Abbildung dargestellt.
%% Cell type:code id: tags:
``` python
s = lambda t: 1/T0*rect(t/T0)
# PLot
T0 = 4
fig,ax=plt.subplots();
ax.plot(t, s(t), 'rwth:blue');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s(t)$')
ax.set_xlim([-5,5]); ax.set_ylim([0,0.5]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Das System hat die Impulsantwort $\displaystyle h(t) = \frac{1}{T}\varepsilon(t)\mathrm{e}^{-t/T}$ und die Übertragungsfunktion $\displaystyle H(f) = \frac{1}{1+\mathrm{j}2 \pi f T}$ mit $T=RC$. Der Betrag der Übertragungsfunktion ist nachfolgend geplottet.
%% Cell type:code id: tags:
``` python
T=2 # RC system with T=R*C
h = lambda t: 1/T*unitstep(t)*np.exp(-t/T) # impulse response
H = lambda f: 1/(1+2j*np.pi*f*T) # transfer function
# Plot
fig,ax=plt.subplots();
ax.plot(f, np.abs(H(f)), 'rwth:blue');
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow |H(f)|$')
ax.set_xlim([-7.5,7.5]); rwth_plots.axis(ax);
#Hf, f0 = rwth_transforms.dft(h(t), 1/(deltat)); Hf = Hf *2*f[-1]; ax.plot(f0, np.abs(Hf), 'k--');
```
%% Cell type:markdown id: tags:
Das Ausgangssignal $g(t)$ kann nun als Faltung des Eingangssignals $s(t)$ mit der Impulsantwort $h(t)$ des Systems beschrieben werden.
$$g(t) = s(t) \ast h(t)$$
Die Impulsantwort sowie das aus der Faltung resultierende Ausgangssignal sind in der folgenden Abbildung dargestellt.
%% Cell type:code id: tags:
``` python
gt = convolution(s, h) # numerical convolution
# Plot
fig,ax = plt.subplots();
ax.plot(t, h(t), 'k--', label=r'$h(t)$');
ax.plot(t,gt, 'rwth:blue', label=r'$g(t)$');
ax.set_xlabel(r'$\rightarrow t$'); ax.legend(loc=2)
ax.set_xlim([-11.5,11.5]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Anstatt im Zeitbereich eine Faltung durchzuführen, kann das Ergebnis auch über eine Multiplikation im Frequenzbereich berechnet werden. Hierfür muss die Fouriertransformierte $S(f)$ des Eingangssignals mit der Übertragungsfunktion $H(f)$ des Systems multipliziert werden:
$G(f) = S(f) H(f)$
Aus $G(f)$ kann dann mittels Rücktransformation $G(t)$ berechnet werden.
Aus $G(f)$ kann dann mittels Rücktransformation $g(t)$ berechnet werden.
%% Cell type:code id: tags:
``` python
Gf, f0 = rwth_transforms.dft(gt, 1/(deltat)); Gf = Gf *2*f[-1];
# Plot
fig,ax = plt.subplots();
ax.plot(f, np.abs(H(f)), 'k--', label=r'$|H(f)|$');
ax.plot(f0, np.abs(Gf), 'rwth:blue', label=r'$|G(f)|$');
ax.set_xlabel(r'$\rightarrow f$'); ax.legend(loc=2)
ax.set_xlim([-7.5,7.5]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
## Demonstration
In dieser Demo kann das Verhalten der Übertragung eines Rechteckimpuls über ein System mit der Impulsantwort $h(t)$ bei Variation der Breite $T_0$ des Rechteckimpulses betrachtet werden. Auf der linken Seite sind die Eingangsfunktion $s(t)$, sowie der Betrag der Übertragungsfunktion $|S(f)|$ dargestellt. Auf der rechten Seite ist oben die Impulsantwort $h(t)$ des Systems sowie das resultierende Ausgangssignal $g(g)$ im Zeitbereich zu sehen. Darunter sind die zugehörigen Beträge der Funktionen im Frequenzbereich dargestellt.
In dieser Demo kann das Verhalten der Übertragung eines Rechteckimpuls über ein System mit der Impulsantwort $h(t)$ bei Variation der Breite $T_0$ des Rechteckimpulses betrachtet werden. Auf der linken Seite sind die Eingangsfunktion $s(t)$, sowie der Betrag der Übertragungsfunktion $|S(f)|$ dargestellt. Auf der rechten Seite ist oben die Impulsantwort $h(t)$ des Systems sowie das resultierende Ausgangssignal $g(t)$ im Zeitbereich zu sehen. Darunter sind die zugehörigen Beträge der Funktionen im Frequenzbereich dargestellt.
%% Cell type:code id: tags:
``` python
plt.close(); fig,axs = plt.subplots(2,2, gridspec_kw = {'width_ratios':[1, 2]});
@widgets.interact(T0=widgets.FloatSlider(min=0.1, max=2, step=0.1, value=1, description='$T_0$', continuous_update=True))
def update_plot(T0):
s = lambda t: 1/T0*rect(t/T0)
h = lambda t: 1/T*unitstep(t)*np.exp(-t/T) # RC system with T=R*C
H = lambda f: 1/(1+2j*np.pi*f*T)
gt = convolution(s, h) # numerical convolution
Sf, f0 = rwth_transforms.dft(s(t), 1/(deltat)); Sf = Sf *2*f[-1];
Gf, _ = rwth_transforms.dft(gt, 1/(deltat)); Gf = Gf *2*f[-1];
# Update plot
if not axs[0,0].lines:
ax = axs[0,0];
ax.plot(t, s(t), 'rwth:blue')
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s(t)$');
ax.set_xlim([-1.1,1.1]); rwth_plots.axis(ax);
ax = axs[1,0];
ax.plot(f0, np.abs(Sf), 'rwth:blue')
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow |S(f)|$');
ax.set_xlim([-11.5,11.5]); rwth_plots.axis(ax);
ax = axs[0,1]; ax.set_title('Zeitbereich')
ax.plot(t, h(t), 'k--', label=r'$h(t)$');
ax.plot(t, gt, 'rwth:blue', label=r'$g(t)$');
ax.set_xlabel(r'$\rightarrow t$'); ax.legend(loc=2)
ax.set_xlim([-11.5,11.5]); rwth_plots.axis(ax);
ax = axs[1,1]; ax.set_title('Frequenzbereich')
ax.plot(f, np.abs(H(f)), 'k--', label=r'$|H(f)|$');
ax.plot(f0, np.abs(Gf), 'rwth:blue', label=r'$|G(f)|$');
ax.set_xlabel(r'$\rightarrow f$'); ax.legend(loc=2)
ax.set_xlim([-11.5,11.5]); rwth_plots.axis(ax);
plt.tight_layout();
else:
axs[0,0].lines[0].set_ydata(s(t))
axs[1,0].lines[0].set_ydata(np.abs(Sf))
axs[0,1].lines[1].set_ydata(gt)
axs[1,1].lines[1].set_ydata(np.abs(Gf))
rwth_plots.update_ylim(axs[0,0], s(t), 0.19, np.max(s(t)));
```
%% Cell type:markdown id: tags:
## Aufgaben
* Variiere $T_0$. Wie sieht der Rechteckimpuls bei kleinen Werten, wie bei großen Werten aus?
* Was passiert bei Änderung von $T_0$ mit dem Betrag der Übertragungsfunktion $|S(f)|$?
* Wie ändert sich das Ausgangssignal $g(t)$ mit kleiner werdendem $T_0$? Was passiert im Frequenzbereich?
* Das kleinstmögliche $T_0$ ist hier 0.1. Wieso überlagern sich die Kurven für $g(t)$ und $h(t)$ bzw in diesem Fall fast?
* Das kleinstmögliche $T_0$ ist hier 0.1. Wieso überlagern sich die Kurven für $g(t)$ und $h(t)$ in diesem Fall fast?
* Was würde passieren, wenn $T_0$ noch kleiner wird? Wie sähe die zugehörige Übertragungsfunktion des Eingangssignals $|S(f)|$ 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