Commit 51d30994 authored by Christian Rohlfing's avatar Christian Rohlfing

- major changes in Abtastung

- new file for fourier series
parent 8b3430ae
......@@ -46,8 +46,11 @@
"\n",
"$$S_\\mathrm{a}(f) = \\frac{1}{T}\\sum\\limits_{k=-\\infty}^\\infty S\\left(f-\\frac{k}{T}\\right) \\text{.}$$\n",
"\n",
"Die Wiederholungen sind bei Vielfachen der Abtastrate $r=\\frac{1}{T}$ positioniert. \n",
"\n",
"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. \n",
"Hier wird das ideale Tiefpassfilter $H_\\mathrm{TP}(f)=\\mathrm{rect}(f)$ verwendet."
"Hier wird das ideale Tiefpassfilter \n",
"$$H_\\mathrm{TP}(f)=\\mathrm{rect}\\left(\\frac{f}{2 f_\\mathrm{g}}\\right)$$ mit Grenzfrequenz $f_\\mathrm{g} = \\frac{r}{2}$ verwendet."
]
},
{
......@@ -55,28 +58,109 @@
"metadata": {},
"source": [
"Zur Auswahl stehen vier Signale $s(t)$:\n",
"* $s(t) = \\cos(2 \\pi t)$, \n",
"* $s(t) = \\mathrm{si}(2 \\pi t)$,\n",
"* $s(t) = \\mathrm{rect} (t)$ und\n",
"* $s(t) = \\Lambda(t)$.\n",
"* $s(t) = \\cos(2 \\pi F t)$ mit $S(f) = \\frac{1}{2}\\delta(f-F)+\\frac{1}{2}\\delta(f+F)$, \n",
"* $s(t) = \\mathrm{si}(2 \\pi F t)$ mit $S(f) = \\frac{1}{2 |F|}\\mathrm{rect}\\left(\\frac{f}{2F}\\right)$,\n",
"* $s(t) = \\mathrm{rect} (F t)$ mit $S(f) = \\frac{1}{|F|}\\mathrm{si}\\left(\\frac{\\pi f}{F}\\right)$ und\n",
"* $s(t) = \\Lambda(F t)$ mit $S(f) = \\frac{1}{|F|}\\mathrm{si}^2\\left(\\frac{\\pi f}{F}\\right)$.\n",
"\n",
"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!\n",
"\n",
"Zunächst werden $s(t)$ und $s_\\mathrm{a}(t)$ im Zeitbereich betrachtet. Weiterhin wird das zu $s_\\mathrm{a}(t)$ gehörige Spektrum $S_\\mathrm{a}(f)$ dargestellt. In der gleichen Abbildung ist die Übertragungsfunktion $H_\\mathrm{TP}(f)$ des Rekonstruktionsfilters gezeigt. In der letzten Abbildung wird nun das rekonstruierte Signal $g(t)$ gezeigt. Im Alias-freien Fall gilt $g(t)=s(t)$."
"Zunächst werden $s(t)$ und $s_\\mathrm{a}(t)$ im Zeitbereich betrachtet. Weiterhin wird das zu $s_\\mathrm{a}(t)$ gehörige Spektrum $S_\\mathrm{a}(f)$ dargestellt. In der gleichen Abbildung ist die Übertragungsfunktion $H_\\mathrm{TP}(f)$ des Rekonstruktionsfilters gezeigt. In der letzten Abbildung wird nun das rekonstruierte Signal $g(t)$ gezeigt. Im Alias-freien Fall für cos-Funktion und si-Funktion gilt $g(t)=s(t)$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"metadata": {
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"# Open figures and create GUI elements\n",
"sPlot = SamplingPlot()\n",
"signal = interactive(sPlot.update_signal, signal=widgets.Dropdown(\n",
" options=['cos-Funktion', 'si-Funktion', 'Rechteckimpuls', 'Dreieckimpuls'], description=r'$s(t)$'))\n",
"T = interactive(sPlot.update_T, T=widgets.FloatSlider(min=0.1, max=2.55, value=0.1, step=.1, description=r'$T$'))\n",
"display(VBox([signal, T]));"
"r = 2; T = 1/r; # sampling frequency\n",
"signals_t = {'cos-Funktion': lambda t: np.cos(2 * np.pi * t),\n",
" 'si-Funktion': lambda t: si(2 * np.pi * t),\n",
" 'Rechteckimpuls': lambda t: rect(t / 1.05),\n",
" 'Dreieckimpuls': tri}\n",
"\n",
"signals_f = {'cos-Funktion': lambda f, F: np.isin(f/F, f[findIndOfLeastDiff(f/F, [-1, 1])]/F) * 0.5,\n",
" 'si-Funktion': lambda f, F: 1/(2*np.abs(F))*rect(f / (2*F)),\n",
" 'Rechteckimpuls': lambda f, F: 1/np.abs(F)*si(np.pi * f / F),\n",
" 'Dreieckimpuls': lambda f, F: 1/np.abs(F)*si(np.pi * f/F) ** 2}\n",
"#f = t;\n",
"t,deltat = np.linspace(-10,10,50001, retstep=True) # t-axis\n",
"f,deltaf = np.linspace(-50,50,len(t), retstep=True) # f-axis\n",
"kMax = 16 # number of k values in sum for Sa(f)\n",
"\n",
"# Plot\n",
"plt.close(); fig, axs = plt.subplots(3, 1)\n",
"@widgets.interact(s_type=widgets.Dropdown(options=list(signals_t.keys()), description=r'Wähle $s(t)$:'),\n",
" F=widgets.FloatSlider(min=0.1, max=2, value=0.9, step=.1, description=r'$F$', style=ient_wdgtl_style))\n",
"def update_plots(s_type, F):\n",
" s = lambda t: signals_t[s_type](t*F); \n",
" S = lambda f: signals_f[s_type](f, F);\n",
" nT, snT = ient_sample(t, s(t), T)\n",
" \n",
" # Construct sampled spectrum\n",
" Sa = np.zeros_like(f)\n",
" for k in np.arange(-kMax, kMax+1): # evaluate infinite sum only for 2*kMax+1 elements\n",
" Sa += S(f-k/T)\n",
" Sa = Sa/T\n",
" \n",
" # Reconstruct g(t)\n",
" H_lp = rect(f/(r+0.001)) # reconstruction filter\n",
" G = Sa * H_lp * T; # reconstruction\n",
" g = ient_idft(G); \n",
" g = np.fft.ifftshift(np.real(g)); # IDFT\n",
" if not s_type == 'cos-Funktion': \n",
" g /= (len(f)/(2*f[-1])) # Parseval :)\n",
" else:\n",
" fSadirac = f[np.where(Sa)]; Sadirac = Sa[np.where(Sa)]\n",
" fSdirac = f[np.where(S(f))]; Sdirac = S(f)[np.where(S(f))]\n",
" \n",
" # Plot\n",
" if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time\n",
" ax = axs[0]; ax.set_title('Zeitbereich');\n",
" ax.plot(t, s(t), color='rwth', linestyle='--', label=r'$s(t)$');\n",
" ient_plot_dirac(ax, nT, snT, 'rot', label=r'$s_\\mathrm{a}(t)$')\n",
" ax.set_xlabel(r'$\\rightarrow t$');\n",
" ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);\n",
" \n",
" ax = axs[1]; ax.set_title('Frequenzbereich');\n",
" ax.plot(f, H_lp, '-', color='black', label=r'$H_\\mathrm{TP}(f)$')\n",
" if not s_type == 'cos-Funktion':\n",
" ax.plot(f, Sa, '-', color='rot', label=r'$S_a(f)$'); \n",
" ient_plot_dirac(ax, [], [], 'rot');\n",
" else:\n",
" ax.plot(f, np.ones_like(f)*np.nan, '-', color='rot', label=r'$S_a(f)$'); \n",
" ient_plot_dirac(ax, fSadirac, Sadirac, 'rot');\n",
" ax.plot(f, S(f), color='rwth', linestyle='--', linewidth=1, label=r'$S(f)$')\n",
" ax.set_xlim([-7.5,7.5]); ax.set_ylim([-1,2]); ax.legend(loc=2);\n",
" ax.set_xlabel(r'$\\rightarrow f$'); ient_grid(ax); ient_axis(ax);\n",
" txt,_=ient_annotate_xtick(ax, r'$r=2$', r, -.1, 'black'); txt.get_bbox_patch().set_alpha(1);\n",
" txt,_=ient_annotate_xtick(ax, r'$f_\\mathrm{g}$', r/2, -.1, 'black'); txt.get_bbox_patch().set_alpha(1);\n",
" \n",
" ax = axs[2]; ax.set_title('Zeitbereich (nach Rekonstruktion)');\n",
" ax.plot(t, s(t), color='rwth', linestyle='--', label=r'$s(t)$');\n",
" ax.plot(t/deltat/(f[-1]*2), g, 'grun', label=r'$g(t)$');\n",
" ax.set_xlabel(r'$\\rightarrow t$');\n",
" ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);\n",
" plt.tight_layout()\n",
" else:\n",
" axs[0].lines[0].set_ydata(s(t))\n",
" ient_dirac_set_data(axs[0].containers, nT, snT)\n",
" if not s_type == 'cos-Funktion':\n",
" ient_dirac_set_data(axs[1].containers, [], [])\n",
" axs[1].lines[1].set_ydata(Sa);\n",
" else:\n",
" ient_dirac_set_data(axs[1].containers, fSadirac, Sadirac); \n",
" axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan);\n",
" axs[1].lines[-3].set_ydata(S(f)); \n",
" axs[2].lines[0].set_ydata(s(t))\n",
" axs[2].lines[1].set_ydata(g);\n",
" ient_update_ylim(axs[1], Sa, 0.19, np.max(Sa));\n",
" ient_update_ylim(axs[2], g, 0.19, np.max(g));"
]
},
{
......
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": false,
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"# Copyright 2019 Institut für Nachrichtentechnik, RWTH Aachen University\n",
"%matplotlib widget\n",
"\n",
"import ipywidgets as widgets\n",
"from ipywidgets import interact, interactive, fixed, Layout\n",
"\n",
"from ient_nb.ient_plots import *\n",
"from ient_nb.ient_signals import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div>\n",
" <img src=\"ient_nb/figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
"</div>\n",
"\n",
"# Fourier-Reihenkoeffizienten"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Im Folgenden soll die periodische Rechteckfunktion\n",
"$$s_\\mathrm{p}(t) = \n",
"\\mathrm{rect}\\left(\\frac{t}{T_1}\\right) \\ast\n",
"\\sum_{n=-\\infty}^\\infty \\delta(t-nT)\n",
"$$\n",
"durch eine *endliche* Fourier-Summe $s_{\\mathrm{p},N}(t)$ approximiert werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"t = np.linspace(-3,3,10000) # t-axis\n",
"T = 1; F = 1/T; # periodicity T\n",
"T1 = T/2\n",
"\n",
"# Parts of the infinite rect sum\n",
"Nmax = 3 # should be infinity :-)\n",
"s = np.zeros_like(t)\n",
"for n in np.arange(-Nmax,Nmax+1):\n",
" s = s + rect((t-n)/T1)\n",
" \n",
"# Plot\n",
"fig,ax = plt.subplots(figsize=(6,3)); ax.plot(t, s, 'rwth'); \n",
"ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow s_{\\mathrm{p}}(t)$');\n",
"ax.set_xlim([-2.9, 2.9]); ax.set_ylim([0, 1.09]); ient_axis(ax);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die zugehörigen Fourier-Reihenkoeffizienten lassen sich (wie im Buch) berechnen zu\n",
"\n",
"$$\n",
"S_\\mathrm{p}(k)\n",
"=\n",
"\\frac{\\sin\\left(k\\pi\\frac{T_1}{T}\\right)}{k\\pi}\\quad\\text{mit }k\\neq 0\n",
"$$\n",
"\n",
"und $S_\\mathrm{p}(k=0) = \\frac{T_1}{T}$. Im Folgenden ist $T=\\frac{1}{F} = 1$.\n",
"\n",
"Approximation der Fourier-Summe durch eine endliche Summe (Summation bis zu $\\pm N$ anstelle $\\pm \\infty$) im Zeitbereich\n",
"\n",
"$$\n",
"s_{\\mathrm{p},N}(t)\n",
"=\n",
"\\sum_{k=-N}^N S_\\mathrm{p}(k) \\mathrm{e}^{\\mathrm{j} 2 \\pi k F t}\n",
"\\text{ .}\n",
"$$\n",
"\n",
"Da $s_\\mathrm{p}(t)$ hier reell (und $S_\\mathrm{p}(-k) = S_\\mathrm{p}^\\ast(k)$):\n",
"\n",
"$$\n",
"s_{\\mathrm{p},N}(t)\n",
"=\n",
"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\\}\n",
"\\text{ .}\n",
"$$\n",
"\n",
"Zunächst für ein einfaches Beispiel mit $N=4$:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"N = 4\n",
"k = np.arange(0,N)\n",
"# Fourier series coefficients\n",
"Sp = np.zeros(N)\n",
"Sp[0] = T1/T # k=0\n",
"Sp[1::] = np.sin(k[1::]*np.pi*T1/T)/(k[1::]*np.pi) # k > 0\n",
"\n",
"# Plot\n",
"fig,ax = plt.subplots(); ient_stem(ax, k, Sp, 'rwth');\n",
"ax.set_xlabel(r'$\\rightarrow k$'); ax.set_ylabel(r'$\\uparrow S_{\\mathrm{P}}(k)$'); ient_axis(ax);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die einzelnen Summanden \n",
"$\n",
"2 \\mathrm{Re}\\left\\{ S_\\mathrm{p}(k) \\mathrm{e}^{\\mathrm{j} 2 \\pi k F t} \\right\\}\n",
"$\n",
"sowie das Resultat $s_{\\mathrm{p},N}(t)$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Approximated time signal\n",
"sp = Sp[0]*np.ones_like(t) # DC\n",
"\n",
"fig,axs = plt.subplots(2,1); colors = ['grun', 'orange', 'magenta']; ax = axs[0];\n",
"ax.plot(t,sp, 'rwth-50', linestyle='--', label=r'$S_\\mathrm{p}(0)$')\n",
"legend = np.array([r'$k==0$'])\n",
"for kIter in k[1::]:\n",
" spIter = 2*np.real(Sp[kIter]*np.exp(2j*np.pi*kIter*F*t));\n",
" sp = sp + spIter;\n",
" # Plot\n",
" ax.plot(t,spIter, color=colors[kIter-1], linestyle='--', label=r'$k={}$'.format(kIter))\n",
" \n",
"ax.set_xlabel(r'$\\rightarrow t$'); ax.legend(loc='lower left');\n",
"ax.set_xlim([-1.6,1.6]); ax.set_ylim([-1.1,1.1]); ient_axis(ax); \n",
"\n",
"ax = axs[1]; ax.plot(t, sp)\n",
"ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow s_{\\mathrm{P},N}(t)$');\n",
"ax.set_xlim([-1.6,1.6]); ient_axis(ax);"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Demo\n",
"\n",
"Demonstration für variable $N$ und $T_1$"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": false,
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"fig,axs = plt.subplots(2,1); #fig.canvas.layout.height = '600px';\n",
"@widgets.interact(N=widgets.IntSlider(min=1, max=50, step=1, description='$N$', continuous_update=False),\n",
" T1=widgets.FloatSlider(min=0.125, max=.75, step=0.125, value=.5, description='$T_1$', \n",
" continuous_update=False, readout_format='.3f',))\n",
"def update_plot(N, T1):\n",
" # Snippet of time signal\n",
" s = np.zeros_like(t)\n",
" for n in np.arange(-Nmax,Nmax+1):\n",
" s = s + rect((t-n)/T1)\n",
" \n",
" # Fourier series coefficients\n",
" k = np.arange(0,N)\n",
" Sp = np.zeros(N)\n",
" Sp[0] = T1/T\n",
" Sp[1::] = np.sin(k[1::]*np.pi*T1/T)/(k[1::]*np.pi)\n",
" \n",
" # Approximated time signal\n",
" sp = Sp[0]*np.ones_like(t) # DC\n",
" for kIter in k[1::]:\n",
" sp = sp + 2*np.real(Sp[kIter]*np.exp(2j*np.pi*kIter*F*t));\n",
"\n",
" k = np.concatenate((-k[::-1],k[1::]));\n",
" Sp = np.concatenate((Sp[::-1],Sp[1::]))\n",
"\n",
" # Plot\n",
" if not axs[0].lines: # create plot\n",
" ax = axs[0]; ax.plot(t, s, 'k--')\n",
" ax.plot(t, sp, 'rwth'); \n",
" ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow s_{\\mathrm{P},N}(t)$');\n",
" ax.set_xlim([-1.6,1.6]); ax.set_ylim([-.2, 1.2]); ient_axis(ax);\n",
" \n",
" ax = axs[1]; ient_stem(ax, k, Sp, 'rwth');\n",
" ax.set_xlabel(r'$\\rightarrow k$'); ax.set_ylabel(r'$\\uparrow S_{\\mathrm{P}}(k)$');\n",
" ient_axis(ax); ax.set_ylim([-.29,.89])\n",
" else: # update plot\n",
" axs[0].lines[0].set_ydata(s); axs[0].lines[1].set_ydata(sp);\n",
" ient_stem_set_data(axs[1].containers[0], k, Sp);plt.show()\n",
" axs[1].set_xlim([-N+.5, N-.5])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"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). \n",
"\n",
"Please attribute the work as follows: \n",
"*Christian Rohlfing, Übungsbeispiele zur Vorlesung \"Grundgebiete der Elektrotechnik 3 - Signale und Systeme\"*, gehalten von Jens-Rainer Ohm, 2019, [Institut für Nachrichtentechnik](http://www.ient.rwth-aachen.de), RWTH Aachen University."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Subproject commit fefddbd0a49dfe99deb8d0e5b4292836dec108a1
Subproject commit 7418cc111440424b7e809f26cab228c4d993f46e
......@@ -26,6 +26,7 @@
" * [Demo Laplace-Transformation](GDET3%20Laplace-Transformation.ipynb)\n",
"3. Fourier-Bechreibung von Signalen und Systemen\n",
" * [RL-Hochpass](GDET3%20RL-Hochpass.ipynb)\n",
" * [Fourier-Reihe](GDET3%20Fourier-Reihenkoeffizienten.ipynb)\n",
"4. Diskrete Signale und Systeme\n",
" * [Abtastung](GDET3%20Abtastung.ipynb)\n",
" * [Diskrete Faltung](GDET3%20Diskrete%20Faltung.ipynb)\n",
......@@ -79,5 +80,5 @@
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 4
}
Markdown is supported
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