GDET3 Reale Abtastung.ipynb 23.6 KB
Newer Older
Christian Rohlfing's avatar
Christian Rohlfing committed
1
2
3
4
5
6
7
8
9
10
11
12
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
   "outputs": [],
   "source": [
13
    "# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    "%matplotlib widget\n",
    "\n",
    "from ipywidgets import interact, interactive, fixed, HBox, VBox\n",
    "import ipywidgets as widgets\n",
    "from IPython.display import clear_output, display, HTML\n",
    "\n",
    "from ient_nb.ient_plots import *\n",
    "from ient_nb.ient_transforms import *\n",
    "from ient_nb.ient_signals import *\n",
    "\n",
    "signals_t = {'cos-Funktion':    lambda t: np.cos(2 * np.pi * t),\n",
    "             'sin-Funktion':    lambda t: np.sin(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",
30
31
    "signals_f = {'cos-Funktion':   lambda f, F: np.isin(f/F, f[find_ind_least_diff(f/F, [-1, 1])]/F) * 0.5,\n",
    "             '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,\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
    "             '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}"
   ]
  },
  {
   "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",
    "\n",
    "# Reale Abtastung\n",
    "\n",
48
    "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.\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
49
50
51
    "\n",
    "## Shape-top Abtastung\n",
    "\n",
52
    "Bei der Shape-top Abtastung wird das kontinuierliche Signal $s(t)$ mit Abstand $T=\\frac{1}{r}$ abgetastet. \n",
53
    "Anstatt einer Diracfolge wird eine Folge schmaler Rechteckimpulse mit endlicher Dauer $T_0$ verwendet. Das abgetastete Signal $s_0(t)$ ergibt sich zu\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
54
55
56
57
    "\n",
    "$$\n",
    "s_0(t) \n",
    "= s(t) \\cdot \\sum\\limits_{n=-\\infty}^\\infty \\mathrm{rect}\\left(\\frac{t-nT}{T_0}\\right) \n",
58
    "= s(t) \\cdot \\left[\\mathrm{rect}\\left(\\frac{t}{T_0}\\right) \\ast \\sum\\limits_{n=-\\infty}^\\infty \\delta(t-nT) \\right].\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
59
60
    "$$\n",
    "\n",
61
    "Im Frequenzbereich folgt durch Transformation\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
62
63
64
65
    "$$\n",
    "S_0(f) \n",
    "= 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]\n",
    "=\n",
66
    "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{.}\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
67
68
    "$$\n",
    "\n",
69
    "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.\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
70
    "\n",
71
    "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)$."
Christian Rohlfing's avatar
Christian Rohlfing committed
72
73
74
75
76
77
78
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Flat-top Abtastung\n",
79
    "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\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
80
81
82
    "\n",
    "$$\n",
    "s_0(t) \n",
Christian Rohlfing's avatar
Christian Rohlfing committed
83
    "= \\sum\\limits_{n=-\\infty}^\\infty s(nT) \\mathrm{rect}\\left(\\frac{t}{T}-\\frac{1}{2}-nT\\right)\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
84
    "= s_\\mathrm{a}(t) \\ast \\mathrm{rect}\\left(\\frac{t}{T}-\\frac{1}{2}\\right)\n",
85
    "= \\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{.}\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
86
87
    "$$\n",
    "\n",
88
    "Im Frequenzbereich folgt dann\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
89
90
91
    "$$\n",
    "S_0(f) \n",
    "= S_\\mathrm{a}(f) \\cdot T \\cdot \\mathrm{si}(\\pi f T) \\cdot \\mathrm{e}^{-\\mathrm{j}\\pi f T}\n",
92
    "= \\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{.}\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
93
94
    "$$\n",
    "\n",
95
    "In der Demonstration kann der Unterschied zwischen der Shape-top und der Flat-top Abtastung nocheinmal anschaulich betrachtet werden."
Christian Rohlfing's avatar
Christian Rohlfing committed
96
97
98
99
100
101
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
102
    "## Beispiel\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
103
104
    "### Abtastung\n",
    "\n",
105
106
107
108
109
110
    "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.\n",
    "Das abgetastete Signal \n",
    "$s_\\mathrm{a}(t) = \\sum\\limits_{n=-\\infty}^\\infty s(nT)\\cdot\\delta(t-nT)$ und das Spektrum des abgetasteten Signals \n",
    "$S_\\mathrm{a}(f) = \\frac{1}{T} \\sum\\limits_{k=-\\infty}^\\infty S(f-kr)$ sind ebenfalls abgebildet. \n",
    "\n",
    "Das Spektrum des abgetasteten Signals zeigt die für die Abtastung typischen spektralen Wiederholungen. "
Christian Rohlfing's avatar
Christian Rohlfing committed
111
112
113
114
115
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
116
117
118
119
120
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
Christian Rohlfing's avatar
Christian Rohlfing committed
121
122
123
124
125
126
127
128
129
130
   "outputs": [],
   "source": [
    "# Construction of s(t) and corresponding spectrum S(f)\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",
    "\n",
    "F = 0.9 # frequency of the signal\n",
    "s = lambda t: signals_t['cos-Funktion'](t*F); \n",
    "S = lambda f: signals_f['cos-Funktion'](f, F);\n",
    "\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
131
    "# Ideal sampling: Construction of sa(t) and Sa(f)\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    "r = 2; T = 1/r; # sampling rate\n",
    "\n",
    "## Time domain\n",
    "nT, snT = ient_sample(t, s(t), T)\n",
    "\n",
    "## Frequency domain\n",
    "Sa = np.zeros_like(S(f))\n",
    "kMax = 16 # number of k values in sum for Sa(f), should be infinity :)\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",
    "fSadirac = f[np.where(Sa)]; Sadirac = Sa[np.where(Sa)]\n",
    "\n",
    "# Plot\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
146
    "## Time domain\n",
147
    "fig, axs = plt.subplots(2,1, **ient_landscape)\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
148
149
150
151
    "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$'); ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
152
    "## Frequency domain\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
153
154
155
    "ax = axs[1];  ax.set_title('Frequenzbereich');\n",
    "ient_plot_dirac(ax, fSadirac, Sadirac, 'rot', label=r'$S_\\mathrm{a}(f)$');\n",
    "ient_plot_dirac(ax, f[np.where(S(f))], S(f)[np.where(S(f))], 'rwth', label=r'$S(f)$');\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
156
    "ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_xlabel(r'$\\rightarrow f$'); ient_grid(ax); ient_axis(ax);\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
157
158
159
160
161
162
163
    "txt,_=ient_annotate_xtick(ax, r'$r=2$', r, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
164
    "Nun wird das abgetastete Signal $s_0(t)$ im Zeitbereich betrachtet, welches mittels Flat-top Abtastung erzeugt wurde:\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
165
166
167
    "$$\n",
    "s_0(t) \n",
    "= s_\\mathrm{a}(t) \\ast \\mathrm{rect}\\left(\\frac{t}{T}-\\frac{1}{2}\\right)\n",
168
169
170
171
172
    "= \\sum\\limits_{n=-\\infty}^\\infty s(nT) \\mathrm{rect}\\left(\\frac{t}{T}-\\frac{1}{2}-nT\\right).\n",
    "$$\n",
    "\n",
    "Die Abtastrate ist ebenfalls $r=2$.\n",
    "Für die Flat-top Abtastung charakteristisch wird der Signalwert bis zum nächsten Abtastwert gehalten. "
Christian Rohlfing's avatar
Christian Rohlfing committed
173
174
175
176
177
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
178
179
180
181
182
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
Christian Rohlfing's avatar
Christian Rohlfing committed
183
184
185
186
187
188
189
190
191
   "outputs": [],
   "source": [
    "# Time-Domain\n",
    "s0 = np.zeros_like(t) # sum of rects\n",
    "Nmax = np.ceil(t[-1]/T) # Parts of the infinite rect sum, should be infinity :)\n",
    "for n in np.arange(-Nmax,Nmax+1):\n",
    "    s0 = s0 + rect((t-n*T)/T-0.5) * s(n*T)\n",
    "\n",
    "# Plot\n",
192
    "fig, ax = plt.subplots(**ient_landscape); ax.set_title('Zeitbereich')\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
193
194
195
196
197
198
199
200
    "ax.plot(t, s(t), 'rwth', linestyle='--', label=r'$s(t)$'); ax.plot(t, s0, 'rot', label=r'$s_0(t)$')\n",
    "ax.set_xlabel(r'$\\rightarrow t$'); ax.set_xlim([-2.9, 2.9]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
201
202
    "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. \n",
    "$S_0(f)$ ergibt sich also zu\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
203
204
    "$$\n",
    "S_0(f) \n",
205
206
207
    "= S_\\mathrm{a}(f) \\cdot T \\mathrm{si}(\\pi f T) \\cdot \\mathrm{e}^{-j\\pi f T}.\n",
    "$$\n",
    "Die nachfolgende Abbildung verdeutlicht diesen Effekt."
Christian Rohlfing's avatar
Christian Rohlfing committed
208
209
210
211
212
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
213
214
215
216
217
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
Christian Rohlfing's avatar
Christian Rohlfing committed
218
219
220
221
222
223
224
225
   "outputs": [],
   "source": [
    "# Frequency domain\n",
    "S_si = T*si(np.pi*T*f)\n",
    "S_exp = np.exp(-1j*np.pi*f*T)\n",
    "S0 = Sa * S_si * S_exp\n",
    "\n",
    "# Plot\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
226
    "## Magnitude\n",
227
    "fig, axs = plt.subplots(2,1, **ient_landscape); \n",
Christian Rohlfing's avatar
Christian Rohlfing committed
228
229
    "ax = axs[0]; ax.set_title('Betrag')\n",
    "ax.plot(f, np.abs(S_si*S_exp), 'k--', label=r'$|T\\mathrm{si}(\\pi f T)e^{-\\mathrm{j}\\pi f T}|$')\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
230
    "fS0dirac = f[np.where(S0)];   S0dirac = S0[np.where(S0)] # sample S0 and f\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
231
232
    "ient_plot_dirac(ax, fS0dirac, np.abs(S0dirac), 'rot', label=r'$|S_0(f)$|');\n",
    "ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_xlabel(r'$\\rightarrow f$'); ient_grid(ax); ient_axis(ax);\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
233
    "## Phase\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
234
235
236
237
238
239
240
241
242
243
244
245
    "ax = axs[1]; ax.set_title('Phase')\n",
    "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}$')\n",
    "ient_stem(ax, fS0dirac, np.angle(S0dirac), 'rot', label=r'$\\angle S_0(f)$')\n",
    "ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_xlabel(r'$\\rightarrow f$'); ient_grid(ax); ient_axis(ax);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Rekonstruktion\n",
    "\n",
246
    "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.\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
247
248
249
250
251
252
253
254
    "$$\n",
    "H_\\mathrm{eq}(f) = \\frac{1}{T \\cdot \\mathrm{si}(\\pi f T) \\cdot \\mathrm{e}^{-j\\pi f T}}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
255
256
257
258
259
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
Christian Rohlfing's avatar
Christian Rohlfing committed
260
261
262
263
264
265
266
267
268
269
270
   "outputs": [],
   "source": [
    "# Reconstruction filters #plt.close('all')\n",
    "## Ideal Low pass to crop the base band\n",
    "H_lp = rect(f/(r+0.001)) # ideal low pass between -r/2 and r/2\n",
    "## Equalizing filter to compensate the influence of si(...) and exp(...) terms in S_0(f)\n",
    "H_eq = 1/(T*si(np.pi*T*f) * np.exp(-1j*np.pi*f*T))\n",
    "## Overall reconstruction filter\n",
    "H = H_lp * H_eq\n",
    "\n",
    "# Plot\n",
271
    "fig,axs = plt.subplots(2,1, **ient_landscape)\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
272
273
274
275
276
277
278
279
280
281
282
283
284
    "ax = axs[0]\n",
    "ax.plot(f, np.abs(H_eq), 'k--', linewidth=1, label=r'$|H_\\mathrm{eq}(f)|$')\n",
    "ax.plot(f, np.abs(H), 'k', label=r'$|H(f)|$')\n",
    "ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ax.set_ylim([-.1,21]);\n",
    "ax.set_xlabel(r'$\\rightarrow f$'); ient_grid(ax); ient_axis(ax);\n",
    "\n",
    "ax = axs[1]\n",
    "ax.plot(f, np.angle(H_eq), 'k--', linewidth=1, label=r'$\\angle H_\\mathrm{eq}(f)$')\n",
    "ax.plot(f, np.angle(H)*H_lp, 'k', label=r'$\\angle H(f)$')\n",
    "ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); #ax.set_ylim([-.1,11]);\n",
    "ax.set_xlabel(r'$\\rightarrow f$'); ient_grid(ax); ient_axis(ax);"
   ]
  },
Christian Rohlfing's avatar
Christian Rohlfing committed
285
286
287
288
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
289
290
    "Dieses Filter wird nun zur Rekonstruktion angewendet. \n",
    "Das rekonstruierte Signal unter Verwendung des ausgleichenden Filters ist unten abgebildet. Das Originalsignal konnte erfolgreich rekonstruiert werden. "
Christian Rohlfing's avatar
Christian Rohlfing committed
291
292
293
294
295
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
296
297
298
299
300
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
Christian Rohlfing's avatar
Christian Rohlfing committed
301
302
303
304
305
306
307
   "outputs": [],
   "source": [
    "G = S0 * H*T; \n",
    "g = ient_idft(G); g = np.fft.ifftshift(np.real(g)); # IDFT\n",
    "G = np.real(G); # discards small imaginary numbers close to zero\n",
    "\n",
    "# Plot\n",
308
    "fig, axs = plt.subplots(2, 1, **ient_landscape)\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
309
310
311
312
313
314
315
316
317
318
    "ax = axs[0]; fGdirac  = f[np.where(G)]; Gdirac = G[np.where(G)]\n",
    "ient_plot_dirac(ax, fGdirac, Gdirac, 'grun');\n",
    "ax.set_xlabel(r'$\\rightarrow f$'); ax.set_ylabel(r'$\\uparrow G(f)$', bbox=ient_wbbox);\n",
    "ax.set_xlim([-7.5,7.5]); ient_grid(ax); ient_axis(ax);\n",
    "\n",
    "ax = axs[1]; ax.plot(t, s(t), color='rwth', linestyle='--', label=r'$s(t)$');\n",
    "ax.plot(t/deltat/(f[-1]*2), g, color='grun', linestyle='-', label=r'$g(t)$');\n",
    "ax.set_xlabel(r'$\\rightarrow t$'); ax.set_xlim([-7.5,7.5]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);"
   ]
  },
Christian Rohlfing's avatar
Christian Rohlfing committed
319
320
321
322
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
323
    "## Demo\n",
324
325
326
327
328
329
330
331
332
    "In der folgenden interaktiven Demonstration kann nun betrachtet werden, was der Unterschied zwischen der Flat-top und der Shape-top Abtastung ist. \n",
    "Dargestellt sind untereinander:\n",
    "* der Zeitbereich mit dem Originalsignal und dem abgestasteten Signal\n",
    "* der zugehörige Frequenzbereich mit dem Originalspektrum, dem Spektrum des abgetasteten Signal und dem Rekonstruktionsfilter\n",
    "* das rekonstruierte Spektrum\n",
    "* das rekonstruierte Signal im Zeitbereich.\n",
    "\n",
    "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. \n",
    "Ü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. "
Christian Rohlfing's avatar
Christian Rohlfing committed
333
334
335
336
337
338
339
340
341
342
343
344
345
346
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "T0 = T/4 # width of rects for shape-top sampling\n",
    "\n",
347
    "plt.close(); fig, axs = plt.subplots(4, 1, **ient_landscape); plt.tight_layout();\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
    "@widgets.interact(sampling_type=widgets.Dropdown(options=['Shape-top', 'Flat-top'], description=r'Art der Abtastung:', style=ient_wdgtl_style),\n",
    "                  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, continuous_update=False))\n",
    "def update_plots(sampling_type, 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 signal\n",
    "    if sampling_type == 'Shape-top':\n",
    "        u = np.zeros_like(t) # sum of rects\n",
    "        for n in np.arange(-Nmax,Nmax+1):\n",
    "            u = u + rect((t-n*T)/T0)\n",
    "        s0 = s(t) * u\n",
    "    elif sampling_type == 'Flat-top':\n",
    "        s0 = np.zeros_like(t) # sum of rects\n",
    "        for n in np.arange(-Nmax,Nmax+1):\n",
    "            s0 = s0 + rect((t-n*T)/T-0.5) * s(n*T)\n",
    "    \n",
    "    # Construct sampled spectrum\n",
    "    if sampling_type == 'Shape-top':\n",
    "        S0 = np.zeros_like(S(f))\n",
    "        for k in np.arange(-kMax, kMax+1): # evaluate infinite sum only for 2*kMax+1 elements \n",
    "            S0 += S(f-k/T) * si(np.pi*T0*k/T)\n",
    "        S0 = S0*T0/T\n",
    "    elif sampling_type == 'Flat-top':\n",
    "        Sa = np.zeros_like(S(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",
    "        S0 = Sa * si(np.pi*T*f) * np.exp(-1j*np.pi*f*T)\n",
    "        \n",
    "    # Reconstruct g(t)\n",
    "    if sampling_type == 'Shape-top':\n",
    "        H = H_lp\n",
    "        G = S0 * H * T / T0;\n",
    "    elif sampling_type == 'Flat-top':\n",
    "        H = H_lp * H_eq * T\n",
    "        G = S0 * H\n",
    "    g = ient_idft(G); \n",
    "    g = np.fft.ifftshift(np.real(g)); # IDFT\n",
    "        \n",
    "    # Sample for plot\n",
    "    if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':\n",
    "        fS0dirac = f[np.where(S0)];   S0dirac = S0[np.where(S0)]\n",
    "        fSdirac  = f[np.where(S(f))]; Sdirac  = S(f)[np.where(S(f))]\n",
    "        fGdirac  = f[np.where(G)]; Gdirac = G[np.where(G)]\n",
    "        if s_type == 'sin-Funktion':\n",
    "            Sdirac = np.imag(Sdirac); S = lambda f: np.imag(signals_f[s_type](f, F)); \n",
    "            G = np.imag(G); Gdirac = np.imag(Gdirac)\n",
    "        else:\n",
    "            Sdirac = np.real(Sdirac); S0 = np.real(S0); G = np.real(G); Gdirac = np.real(Gdirac)\n",
    "    else:\n",
    "        g /= (len(f)/(2*f[-1])) # Parseval :)\n",
    "        S0dirac = np.zeros_like(f)\n",
    "        G = np.real(G)\n",
    "        \n",
    "    if sampling_type == 'Shape-top': # normalize to T0 for plotting reasons\n",
    "        S0 = S0/T0\n",
    "        S0dirac = S0dirac/T0\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), 'rwth', linestyle='--', label=r'$s(t)$'); \n",
    "        ax.plot(t, s0, 'rot', label=r'$s_0(t)$')\n",
    "        ax.set_xlabel(r'$\\rightarrow t$'); \n",
    "        ax.set_xlim([-2.9, 2.9]); ax.legend(loc=2); ient_grid(ax); ient_axis(ax);\n",
    "        \n",
    "        ax = axs[1];  ax.set_title('Frequenzbereich');\n",
    "        ax.plot(f, np.abs(H), '-', color='black', label=r'$|H(f)|$')\n",
    "        if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':\n",
    "            ax.plot(f, np.ones_like(f)*np.nan, '-', color='rot', label=r'$|S_0(f)|$');\n",
    "            ient_plot_dirac(ax, fS0dirac, np.abs(S0dirac), 'rot');\n",
    "        else:\n",
    "            ax.plot(f, np.abs(S0), '-', color='rot', label=r'$|S_0(f)|$'); \n",
    "            ient_plot_dirac(ax, [], [], '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, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);\n",
    "        txt,_=ient_annotate_xtick(ax, r'$f_\\mathrm{g}$', r/2, -.15, 'black'); txt.get_bbox_patch().set_alpha(1);\n",
    "        \n",
    "        ax = axs[2];\n",
    "        if s_type == 'cos-Funktion' or s_type == 'sin-Funktion':\n",
    "            ax.plot(f, np.ones_like(f)*np.nan, '-', color='grun'); \n",
    "            ient_plot_dirac(ax, fGdirac, Gdirac, 'grun');\n",
    "        else:\n",
    "            ax.plot(f, G, '-', color='grun'); \n",
    "            ient_plot_dirac(ax, [], [], 'rot');\n",
    "        ax.set_xlabel(r'$\\rightarrow f$'); ax.set_ylabel(r'$\\uparrow G(f)$', bbox=ient_wbbox);\n",
    "        ax.set_xlim([-7.5,7.5]); ient_grid(ax); ient_axis(ax);\n",
    "        \n",
    "        ax = axs[3]; 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$'); 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)); axs[0].lines[1].set_ydata(s0); axs[1].lines[-3].set_ydata(S(f)); \n",
    "        axs[1].lines[0].set_ydata(np.abs(H))\n",
    "        if s_type == 'cos-Funktion' or s_type == 'sin-Funktion': # dirac plot\n",
    "            ient_dirac_set_data(axs[1].containers, fS0dirac, np.abs(S0dirac));\n",
    "            axs[1].lines[1].set_ydata(np.ones_like(f)*np.nan); \n",
    "            ient_dirac_set_data(axs[2].containers, fGdirac, Gdirac);   axs[2].lines[0].set_ydata(np.ones_like(f)*np.nan);\n",
    "        else:\n",
    "            axs[1].lines[1].set_ydata(np.abs(S0)); ient_dirac_set_data(axs[1].containers, [], []); \n",
    "            axs[2].lines[0].set_ydata(G); ient_dirac_set_data(axs[2].containers, [], []);\n",
    "            \n",
    "        axs[3].lines[0].set_ydata(s(t)); axs[3].lines[1].set_ydata(g);\n",
    "        \n",
    "        if s_type == 'sin-Funktion': # Adapt labels\n",
    "            axs[1].lines[-3].set_label(r'$\\mathrm{Im}\\{S(f)\\}$');\n",
    "            axs[2].yaxis.label.set_text(r'$\\uparrow \\mathrm{Im}\\{G(f)\\}$');\n",
    "        else:\n",
    "            axs[1].lines[-3].set_label(r'$S(f)$')\n",
    "            axs[2].yaxis.label.set_text(r'$\\uparrow G(f)$');\n",
    "        axs[1].legend(loc=2)\n",
    "        \n",
466
    "    tmp = np.concatenate((np.abs(S0),np.abs(S0dirac),np.abs(H))); ient_update_ylim(axs[1], tmp, 0.19, np.max(np.abs(tmp))); ient_update_ylim(axs[2], G, 0.19, np.max(G));\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
467
468
469
470
471
    "    ient_update_ylim(axs[3], np.concatenate((s(t),g)), 0.19, np.max(np.concatenate((s(t),g))));"
   ]
  },
  {
   "cell_type": "markdown",
472
473
474
475
476
477
478
479
480
481
482
483
484
   "metadata": {},
   "source": [
    "### Aufgaben\n",
    "Wähle eine beliebige Funktion aus.\n",
    "* Wie sieht das abgetastete Signal mit Shape-top Abtastung aus und wie mit Flat-top Abtastung?\n",
    "* Welche Auswirkungen hat die Abtastungsart auf das Spektrum und die Rekonstruktion?\n",
    "* Variiere $F$. Was passiert?\n",
    "* Führe diese Beobachtung für unterschiedliche Funktionen aus. \n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
Christian Rohlfing's avatar
Christian Rohlfing committed
485
486
   "metadata": {},
   "source": [
487
    "___\n",
Christian Rohlfing's avatar
Christian Rohlfing committed
488
489
490
    "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",
491
    "*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."
Christian Rohlfing's avatar
Christian Rohlfing committed
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
   ]
  }
 ],
 "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",
511
   "version": "3.8.1"
Christian Rohlfing's avatar
Christian Rohlfing committed
512
513
514
515
516
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}