Commit 3e368edb authored by Hafiz Emin Kosar's avatar Hafiz Emin Kosar
Browse files

- closed some issues:

  - hid certain cells
  - showing H0 in Laplace-plots
parent 60bf784e
%% Cell type:code id: tags:
``` python
# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget
from ipywidgets import interact, interactive
import ipywidgets as widgets
from IPython.display import clear_output, display, HTML
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
import rwth_nb.plots.mpl_decorations as rwth_plots
from rwth_nb.misc.signals import *
# tau-axis
(tau,deltat) = np.linspace(-20, 20, 4001, retstep=True)
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Beispiel zur Berechnung des Faltungsintegrals
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
## Einleitung
Das Faltungsintegral ist definiert als
$$g(t)
= s(t)\ast h(t)
= \int\limits_{-\infty}^{\infty} s(\tau) h(t-\tau) \mathrm{d}\tau\text{ .}$$
%% Cell type:markdown id: tags:
## Herleitung
### Eingangssignal und Impulsantwort
Wie im Abschnitt 1.6 des Skripts gezeigt, wird hier die Faltung anhand der Impulsantwort des $RC$-Systems
$$h(t) = \frac{1}{T}\varepsilon(t)\mathrm{e}^{-t/T}$$
mit $T=RC$ gezeigt. Es soll dessen Reaktion auf ein Rechteckimpuls der Dauer $T_0$ und der Amplitude $a$
$$s(t) = a\;\mathrm{rect}\left(\frac{t-T_0/2}{T_0}\right)$$
untersucht werden. Beide Funktionen sind in der folgenden Abbildung dargestellt.
%% Cell type:code id: tags:
``` python
# Input signal
T0 = 4 # duration of rect
a = 1/4 # amplitude of rect
s = lambda t: a*rect((t-T0/2)/T0) # Rect impuls with duration T0 and amplitude a
# Impulse response h(t) of RC system
T = 2
h = lambda t: 1/T*unitstep(t)*np.exp(-t/T) # RC system with T=R*C
```
%% Cell type:code id: tags:
``` python
# Plot both signals
fig,ax = plt.subplots(1,1); ax.plot(tau, h(tau), 'rwth:blue'); ax.plot(tau, s(tau), 'rwth:green');
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_xlim([-11,11]); ax.set_ylim([-0.05,0.55]); rwth_plots.axis(ax);
ax.text(T/4, 1/T, r'$h(\tau)$', color='rwth:blue', fontsize=12);
ax.text(T0, a, r'$s(\tau)$', color='rwth:green', fontsize=12);
```
%% Cell type:markdown id: tags:
### Herleitung Faltungsintegral
%% Cell type:markdown id: tags:
$h(\tau)$ wird zunächst gespiegelt, das resultierende Signal ist $h(-\tau)$.
%% Cell type:code id: tags:
``` python
fig,ax = plt.subplots(1,1); ax.plot(tau, h(-tau), 'rwth:blue');
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow h(-\tau)$');
ax.set_xlim([-11,11]); ax.set_ylim([-0.05,0.55]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
Die gespiegelte Version $h(-\tau)$ wird um $t$ verschoben, wobei $t$ sowohl positive als auch negative Werte annehmen kann.
%% Cell type:code id: tags:
``` python
fig,ax = plt.subplots(1,1);
t = 2
ax.plot(tau, h(t-tau), 'rwth:blue');
rwth_plots.annotate_xtick(ax, r'$t>0$', t, -0.05, 'rwth:blue')
t = -3
line_h2,= ax.plot(tau, h(t-tau), 'rwth:red');
rwth_plots.annotate_xtick(ax, r'$t<0$', t, -0.05, 'rwth:red')
ax.set_xlim([-11,11]); ax.set_ylim([-0.09,0.55]);
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow h(t-\tau)$'); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
### Intervall I: $t<0$
Betrachtet man nun $s(\tau)$ und $h(t-\tau)$ für $t<0$ gemeinsam, wird klar, dass in diesem Beispiel für den Integranden des Faltungsintegrals gilt:
$$s(\tau)h(t-\tau)=0$$ und daher $$g(t)=0 \qquad \text{für } t<0 \text{.}$$
Dies gilt für alle Bereiche, in denen keine Überlappung der beiden Signale besteht.
%% Cell type:code id: tags:
``` python
t = -3
fig,ax = plt.subplots(1,1); ax.plot(tau, h(t-tau), 'rwth:blue'); ax.plot(tau, s(tau), '-.', color='rwth:green');
rwth_plots.annotate_xtick(ax, r'$t<0$', t, -0.05, 'rwth:blue');
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow h(t-\tau)$');
ax.set_xlim([-11,11]); ax.set_ylim([-0.09,0.55]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
### Intervall II: $0<t\leq T_0$
Nun taucht $h(t-\tau)$ in $s(\tau)$ ein, und zwar für Zeiten $0<t\leq T_0$:
%% Cell type:code id: tags:
``` python
t = T0/2 # ensure 0<t<=T0
fig,ax = plt.subplots(1,1); ax.plot(tau, h(t-tau), 'rwth:blue'); ax.plot(tau, s(tau), '-.', color='rwth:green');
mask = (tau>0) & (tau<t);
ax.fill_between(tau[mask],0,h(t-tau[mask]), facecolor="none", hatch="//", edgecolor='rwth:black', linewidth=0.0);
rwth_plots.annotate_xtick(ax, r'$0<t\leq T_0$', t, -0.075, 'rwth:blue');
rwth_plots.annotate_xtick(ax, r'$T_0$', T0, -0.125, 'rwth:green');
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow h(t-\tau)$');
ax.set_xlim([-11,11]); ax.set_ylim([-0.19,0.55]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
In diesem Fall ($0<t\leq T_0$) ist das Produkt $s(\tau)h(t-\tau)$ nur im Intervall $0<\tau <t$ von Null verschieden. Dieses Interval begrenzt nun das Faltungsintegral
In diesem Fall ($0<t\leq T_0$) ist das Produkt $s(\tau)h(t-\tau)$ nur im Intervall $0<\tau <t$ von Null verschieden. Dieses Intervall begrenzt nun das Faltungsintegral
$$g(t) = \int\limits_0^t s(\tau)h(t-\tau) \mathrm{d}\tau = a \left(1-\mathrm{e}^{-t/T}\right)\qquad \text{für } 0<t\leq T_0\text{.}$$
Mehr Zwischenschritte werden im Skript gezeigt.
### Intervall III: $t>T_0$
Für alle Zeiten $t>T_0$ liegt $s(\tau)$ komplett in $h(t-\tau)$:
%% Cell type:code id: tags:
``` python
t = T0 + 2 # ensure t>T0
fig,ax = plt.subplots(1,1); ax.plot(tau, h(t-tau), 'rwth:blue'); ax.plot(tau, s(tau), '-.', color='rwth:green');
mask = (tau>0) & (tau<T0);
ax.fill_between(tau[mask],0,h(t-tau[mask]), facecolor="none", hatch="//", edgecolor='rwth:black', linewidth=0.0);
rwth_plots.annotate_xtick(ax, r'$t>T_0$', t, -0.075, 'rwth:blue');
rwth_plots.annotate_xtick(ax, r'$T_0$', T0, -0.125, 'rwth:green');
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow h(t-\tau)$');
ax.set_xlim([-11,11]); ax.set_ylim([-0.19,0.55]); rwth_plots.axis(ax);
```
%% Cell type:markdown id: tags:
In diesem Fall ($t>T_0$) ist das Produkt $s(\tau)h(t-\tau)$ in dem festen Intervall $0<\tau<T_0$, welches von $s(\tau)$ bestimmt wird, von Null verschieden
$$g(t) = \int\limits_0^{T_0} s(\tau)h(t-\tau) \mathrm{d}\tau = a \left(\mathrm{e}^{T_0/T}-1\right)\mathrm{e}^{-t/T}\quad \text{für } t>T_0\text{.}$$
%% Cell type:markdown id: tags:
### Betrachtung aller Intervalle gemeinsam
Insgesamt lässt sich $g(t)$ nun wie folgt darstellen:
%% Cell type:code id: tags:
``` python
def g(t):
out = np.zeros_like(t) # initialize with zeros, covers first interval t<0
# Second interval 0<t<= T0 (cropped with rect(t/T0-1/2))
out += a*(1-np.exp(-t/T))*rect(t/T0-1/2)
# Third interval t>T0 (cropped with unitstep(t-T0))
out += a*(np.exp(T0/T)-1)*np.exp(-t/T)*unitstep(t-T0)
return out
t = tau # now we need the whole t axis
# Plot both s(t) and g(t)
fig,ax = plt.subplots(1,1, figsize=(8,4));
ax.plot(t, g(t)/a, 'rwth:blue');
ax.plot(t, s(t)/a,'-.', color='rwth:green',zorder=1);
rwth_plots.annotate_xtick(ax, r'$T_0$', T0, -0.125, 'rwth:green');
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow g(t)/a$');
ax.set_xlim([-6,16]); ax.set_ylim([-0.15,1.19]); rwth_plots.axis(ax);
ax.text(-5,0.5,'Intervall I', color='rwth:black-50', fontsize=12);
ax.text(2.5,0.5,'II', color='rwth:black-50', fontsize=12); ax.text(7.5,0.5,'III', color='rwth:black-50', fontsize=12);
```
%% Cell type:markdown id: tags:
### Interaktive Demo
%% Cell type:code id: tags:
``` python
fig, axs = plt.subplots(2, 1, figsize=(8,6))
gt = g(t)
@widgets.interact(t=widgets.FloatSlider(min=-5, max=15, step=.2, value=5,description='$t$', continuous_update=True))
def update_plot(t):
t_ind = np.where(tau>=t); t_ind = t_ind[0][0]; # find index corresponding to t
g_plot = gt.copy()/a; g_plot[t_ind:] = np.nan; # cropped g(t)
mask = (tau>0) & (tau<t) & (tau < T0); # mask for hatch
if not axs[0].lines: # call plot() and decorate axes. Usually, these functions take some processing time
ax = axs[0]; line_h,=ax.plot(tau,h(t-tau), 'rwth:blue'); # plot h(t-tau)
rwth_plots.annotate_xtick(ax, r'$t$', t, -0.075, line_h.get_color(), 14);
ax.plot(tau, s(tau),'-.',color='rwth:green', zorder=1)
ax.fill_between(tau[mask],0,h(t-tau[mask]), facecolor="none", hatch="//", edgecolor='k', linewidth=0.0);
ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow h(t-\tau)$');
ax.set_xlim([-6,16]); ax.set_ylim([-.19,.65]); rwth_plots.axis(ax)
ax = axs[1]; ax.plot(tau,g_plot, 'rwth:blue'); # plot g(t)
ax.plot([t, t], [0, gt[t_ind]/a], 'ko--', lw=1);
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow g(t)/a$');
ax.set_xlim([-6,16]); ax.set_ylim([-.15,1.19]);rwth_plots.axis(ax)
else: # If lines exist, replace only xdata and ydata since plt.plot() takes longer time
axs[0].lines[0].set_ydata(h(t-tau));
axs[0].texts[0].set_x(t); axs[0].lines[1].set_xdata([t,t])
axs[0].collections[0].remove();
axs[0].fill_between(tau[mask],0,h(t-tau[mask]), facecolor="none", hatch="//", edgecolor='k', linewidth=0.0);
axs[1].lines[0].set_ydata(g_plot);
axs[1].lines[1].set_xdata([t, t]); axs[1].lines[1].set_ydata([0, gt[t_ind]/a]);
```
%% Cell type:markdown id: tags:
Verschiebe den Schieberegler langsam von links nach rechts. Beobachte die oben beschriebenen Intervalle und ihre Grenzen. An welchen Stellen ändert sich das Verhalten von $g(t)$?
Eine ausführlichere Demo zur Faltung mit einer Auswahl für $s(t)$ und $h(t)$ findet man [hier](GDET3%20Faltung%20GUI.ipynb).
%% Cell type:markdown id: tags:
---
This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT).
Please attribute the work as follows:
*Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2020, Institut für Nachrichtentechnik, RWTH Aachen University.
......
%% Cell type:code id: tags:
``` python
# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget
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)
```
%% Cell type:code id: tags:
``` python
# 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
Die zugehörigen Fourier-Reihenkoeffizienten lassen sich (wie im Buch, Formel (3.27)) 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
```
%% Cell type:code id: tags:
``` python
# 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 $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
```
%% Cell type:code id: tags:
``` python
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
from IPython.display import Markdown as md
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
import rwth_nb.plots.mpl_decorations as rwth_plots
from rwth_nb.misc.signals import *
import rwth_nb.misc.transforms as rwth_transforms
from src.laplace.laplace_plot import pzPoint, pzPlot
t = np.linspace(-6,6,1024)
f = np.linspace(-6,6,1024)
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Laplace-Transformation
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:markdown id: tags:
## Beispiele
$s_1(t) = \mathrm{e}^{-bt}\cdot\epsilon(t)$
transformiert sich zu
$S_1(p) = \frac{1}{b+p}$ mit Konvergenzbereich $\mathrm{Re}\{p\}>\mathrm{Re}\{-b\}$
%% Cell type:code id: tags:
``` python
b = 2
pp = np.array([-b]); pz = np.array([])
roc = np.array([-b, np.inf])
fig,axs = plt.subplots(1,2, **rwth_plots.landscape)
# Laplace-Bereich
ax = axs[0]; rwth_plots.plot_lroc(ax, roc)
ax.plot(np.real(pp), np.imag(pp), **rwth_plots.style_poles); ax.plot(np.real(pp), -np.imag(pp), **rwth_plots.style_poles)
ax.text(3, 4, r'$S_0 =$ ' + str(1), fontsize=12, bbox=rwth_plots.wbbox)
ax.set_xlabel(r'$\rightarrow \mathrm{Re}$'); ax.set_ylabel(r'$\uparrow \mathrm{Im}$');
ax.set_xlim(-5, 5); ax.set_ylim(-5, 5); rwth_plots.grid(ax); rwth_plots.axis(ax)
# Zeitbereich
s1, _, _ = rwth_transforms.ilaplace_ht(t, 1, pp, pz, [1], [], roc)
ax = axs[1]; ax.plot(t, np.real(s1), **rwth_plots.style_graph);
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s_1(t)$'); rwth_plots.grid(ax); rwth_plots.axis(ax)
```
%% Cell type:markdown id: tags:
Da der Konvergenzbereich die imaginäre Achse umschließt, existiert auch die Fouriertransformierte $S_1(f)$:
%% Cell type:code id: tags:
``` python
# Frequenzbereich
S1f = rwth_transforms.ilaplace_Hf(f, 1, pp, pz, [1], [], dB=False)
fig, ax = plt.subplots(1,1)
ax.plot(f, S1f, **rwth_plots.style_graph);
ax.set_xlabel(r'$\rightarrow f$'); ax.set_ylabel(r'$\uparrow S_1(f)$');
ax.set_xlim([-5.5,5.5]); ax.set_ylim([-0.1,0.55]); rwth_plots.grid(ax); rwth_plots.axis(ax)
```
%% Cell type:markdown id: tags:
$s_2(t) = -\mathrm{e}^{-bt}\cdot\epsilon(-t)$
transformiert sich zu
$S_2(p) = \frac{1}{b+p}$ mit Konvergenzbereich $\mathrm{Re}\{p\}<\mathrm{Re}\{-b\}$:
%% Cell type:code id: tags:
``` python
roc = np.array([-np.inf, -b])
fig,axs = plt.subplots(1,2, **rwth_plots.landscape)
# Laplace-Bereich
ax = axs[0]; rwth_plots.plot_lroc(ax, roc); rwth_plots.annotate_order(ax, pp, [1]);
ax.plot(np.real(pp), np.imag(pp), **rwth_plots.style_poles); ax.plot(np.real(pp), -np.imag(pp), **rwth_plots.style_poles)
ax.text(3, 4, r'$S_0 =$ ' + str(1), fontsize=12, bbox=rwth_plots.wbbox)
ax.set_xlabel(r'$\rightarrow \mathrm{Re}$'); ax.set_ylabel(r'$\uparrow \mathrm{Im}$');
ax.set_xlim(-5, 5); ax.set_ylim(-5, 5); rwth_plots.axis(ax); rwth_plots.grid(ax)
# Zeitbereich
s2, _, _ = rwth_transforms.ilaplace_ht(t, 1, pp, pz, [1], [], roc)
ax = axs[1]; ax.plot(t, np.real(s2), **rwth_plots.style_graph);
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s_2(t)$');
ax.set_ylim([-45,5]); rwth_plots.grid(ax); rwth_plots.axis(ax)
```
%% Cell type:markdown id: tags:
Da in diesem Fall der Konvergenzbereich links vom linkesten Pol liegt und somit nicht die imaginäre Achse beinhaltet, existiert die Fouriertransformierte nicht.
Eine ausführlichere Demo zur Laplacetransformation findet man [hier](GDET3%20Laplace-Transformation%20GUI.ipynb).
%% Cell type:markdown id: tags:
___
This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources) (OER). Feel free to use the notebook for your own purposes. The code is licensed under the [MIT license](https://opensource.org/licenses/MIT).
Please attribute the work as follows:
*Emin Kosar, Christian Rohlfing, Übungsbeispiele zur Vorlesung "Grundgebiete der Elektrotechnik 3 - Signale und Systeme"*, gehalten von Jens-Rainer Ohm, 2020, Institut für Nachrichtentechnik, RWTH Aachen University.
......
%% Cell type:code id: tags:
``` python
# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University
%matplotlib widget
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.patches import ConnectionPatch
import numpy as np
import rwth_nb.plots.mpl_decorations as rwth_plots
highlight_args = {'color':'rwth:red', 'marker':'o'}; arrow_args = {'width':1,'headlength':10,'headwidth':10,'fc':'rwth:red'}
anno_args = {'color':'rwth:red-50', 'linestyle':'--', 'arrowstyle':"-", 'coordsA':'data', 'coordsB':'data'}
```
%% Cell type:markdown id: tags:
<div>
<img src="figures/rwth_ient_logo@2x.png" style="float: right;height: 5em;">
</div>
# Primer Komplexe Zahlen
Zum Starten: Im Menü: Run <span class="fa-chevron-right fa"></span> Run All Cells auswählen.
%% Cell type:markdown id: tags:
## Einleitung
Eine komplexe Zahl kann auch als Zeiger interpretiert werden, der sich in einer komplexen Ebene um den Koordinatenursprung dreht. Dies soll hier kurz veranschaulicht werden.
Als Beispiel wird eine reellwertige Wechselspannung
$$
u(t)
=
B \cos(2\pi F t + \phi)
$$
mit Frequenz $F$ und Scheitelwert $B$ betrachtet. Mit dem Spannungszeiger
$$
\mathbf{u}
=
B \mathrm{e}^{\mathrm{j} \phi}
$$
kann $u(t)$ wie folgt beschrieben werden:
$$
u(t)
=
\mathrm{Re}\left\{
\mathbf{u} \cdot \mathrm{e}^{\mathrm{j}2\pi F t}
\right\}
=
\mathrm{Re}\left\{
B \mathrm{e}^{\mathrm{j} \phi} \cdot \mathrm{e}^{\mathrm{j}2\pi F t}
\right\}
=
B \cos(2\pi F t + \phi)
\text{.}$$
Im Folgenden wird $B=F=1$ betrachtet.
%% Cell type:markdown id: tags:
## Demo Zeigerdiagramm
In dieser Demo wird die Interpretation einer komplexen Zahl als Zeiger deutlich gemacht. Die Länge des Zeigers ist konstant. Durch Verschieben des Schiebereglers kann die Phase $\phi$ von
$$
u(t)
=
\mathrm{Re}\left\{
B \mathrm{e}^{\mathrm{j} \phi} \cdot \mathrm{e}^{\mathrm{j}2\pi F t}
\right\}
=
B \cos(2\pi F t + \phi)
\qquad
\text{mit }
\mathbf{u}
=
B \mathrm{e}^{\mathrm{j} \phi}
$$
variiert werden, dies bewirkt eine Drehung des Drehzeigers.
Links oben ist der komplexe Drehzeiger dargestellt, rechts davon die Abbildung des aktuellen Zeigers auf die imaginäre Achse, unten die auf die reelle Achse.
Des Weiteren interessant ist das Verhalten der Phase, welches in der vierten Abbildung dargestellt wird. Die Phase ist definiert als
Des Weiteren interessant ist das Verhalten der Phase, welches in der vierten Abbildung dargestellt wird.
Die Phase ist definiert als
$$
\varphi(t)=\mathrm{arctan}\frac{\mathrm{Im}\{\mathbf{u}\}}{\mathrm{Re}\{\mathbf{u}\}}\pm k\cdot \pi \quad \text{mit}\quad k=\left\{
\begin{array}{l l}
0, \quad \text{für } \mathrm{Re}\{\mathbf{u}\}\geq 0 \\
1, \quad \text{für } \mathrm{Re}\{\mathbf{u}\}< 0
\end{array}
\right\}\text{.}
$$
Hierbei muss beachtet werden, in welchem Quadrant sich der Zeiger aktuell befindet, je nachdem muss das Plus oder das Minus in der Gleichung berücksichtigt werden. Ist der Realteil positiv, befindet sich der Zeiger im ersten oder vierten Quadranten und die Phase läuft entlang der mittleren Linie im Plot. Ist der Realteil negativ, also wenn der Zeiger im zweiten oder dritten Quadranten ist, befindet man sich auf einer der beiden anderen Kurven. Dies ist abhängig vom Imaginärteil. Befindet sich der Zeiger im zweiten Quadranten, ist der Imaginärteil positiv und in der Formel muss $+\pi$ gerechnet werden. Befindet sich der Zeiger im dritten Quadranten, ist der Imaginärteil negativ und in der Formel muss $-\pi$ gerechnet werden.
Hierbei muss beachtet werden, in welchem Quadrant sich der Zeiger aktuell befindet, je nachdem muss das Plus oder das Minus in der Gleichung berücksichtigt werden.
Ist der Realteil positiv, befindet sich der Zeiger im $I$ oder $IV$ Quadranten und die Phase läuft entlang der mittleren Linie im Plot.
Ist der Realteil negativ, also wenn der Zeiger im $II$ oder $III$ Quadranten ist, befindet man sich auf einer der beiden anderen Kurven. Dies ist abhängig vom Imaginärteil.
Befindet sich der Zeiger im $II$ Quadranten, ist der Imaginärteil positiv und in der Formel muss $+\pi$ gerechnet werden.
Befindet sich der Zeiger im $III$ Quadranten, ist der Imaginärteil negativ und in der Formel muss $-\pi$ gerechnet werden.
Dieses Springen kann sehr schön in der Abbildung verfolgt werden.
%% Cell type:code id: tags:
``` python
t = np.linspace(-2,2,5001);
x = np.linspace(-10,10,5001);
F = 1; B = 1;
fig,axs=plt.subplots(2,2,figsize=(6, 6)); fig.tight_layout();
@widgets.interact(phiPi = widgets.FloatSlider(min=-5, max=5, step=0.05, value=0,
description='$\phi/\pi$:', continuous_update=True),
show_lines = widgets.Checkbox(value=True, description='Zeige Hilfslinien', style=rwth_plots.wdgtl_style))
def update_plot(phiPi, show_lines):
global u_versor
phi = phiPi*np.pi
u_versor = B*np.exp(1J*phi)
u_compl = u_versor * np.exp(2J*F*np.pi*t)
ur = np.real(u_versor); ui = np.imag(u_versor)
ku = (ur<0)*(-1)**(ui<0)
xyP = (ur, ui); xyR = (ur, 0); xyI = (0, ui);
if not axs[0,0].lines: # create plots
# Complex number at time t0
ax = axs[0,0]; rwth_plots.axis(ax); ax.axis('equal'); ax00 = ax;
an = np.linspace(0, 2 * np.pi, 100); ax.plot(np.cos(an), np.sin(an), 'rwth:black-50')
ax.annotate("", xy=(np.real(u_versor),np.imag(u_versor)), xytext=(0, 0), arrowprops=arrow_args)
ax.set_xlabel(r'$\rightarrow \mathrm{Re}\{\mathbf{u} \}$'); ax.set_ylabel(r'$\uparrow \mathrm{Im}\{\mathbf{u}\}$')
# Imaginary part
ax = axs[0,1]; ax.plot(t, np.imag(u_compl), 'rwth:black-50'); ax.plot(0, np.imag(u_versor), **highlight_args); rwth_plots.axis(ax);
ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow \mathrm{Im}\left\{\mathbf{u} \cdot \mathrm{e}^{\mathrm{j}2\pi F t}\right\}$'); ax.set_zorder(-1)
# Real part
ax = axs[1,0]; ax.plot(np.real(u_compl),t, 'rwth:black-50'); ax.plot(np.real(u_versor), 0, **highlight_args); rwth_plots.axis(ax);
ax.set_ylabel(r'$\downarrow t$'); ax.set_xlabel(r'$\rightarrow u(t) = \mathrm{Re}\left\{\mathbf{u} \cdot \mathrm{e}^{\mathrm{j}2\pi F t}\right\}$', bbox=rwth_plots.wbbox);
ax.invert_yaxis(); ax.set_zorder(-1)
# Angle
ax = axs[1,1]; rwth_plots.axis(ax);
ax.plot(x, np.arctan(x), 'rwth:blue');
x_ind = np.where(x>0); x_ind = x_ind[0][0]; tmp = np.arctan(x)+np.pi; tmp[x_ind:] = np.nan; ax.plot(x, tmp, 'rwth:blue')
x_ind = np.where(x<0); x_ind = x_ind[0][-1]; tmp = np.arctan(x)-np.pi; tmp[:x_ind] = np.nan; ax.plot(x, tmp, 'rwth:blue')
ax.plot(np.imag(u_versor)/np.real(u_versor), phi, **highlight_args);
ax.set_xlim([-7.5,7.5])
ax.set_xlabel(r'$\rightarrow \mathrm{Im} / \mathrm{Re}$'); ax.set_ylabel(r'$\uparrow \angle\{\mathbf{u}\}$');
ax.set_yticks([-np.pi, -np.pi/2, np.pi/2, np.pi]); ax.yaxis.set_ticklabels([r'$-\pi$',r'$-\pi/2$',r'$\pi/2$', r'$\pi$'])
#fig.tight_layout(); # hide last axis and tighten layout
else: # update plots
annotations = [child for child in axs[0,0].get_children() if isinstance(child, matplotlib.text.Annotation)]
annotations[0].remove()
axs[0,0].annotate("", xy=(np.real(u_versor),np.imag(u_versor)), xytext=(0, 0), arrowprops=arrow_args)
axs[0,1].lines[0].set_ydata(np.imag(u_compl)); axs[0,1].lines[1].set_ydata(np.imag(u_versor))
axs[1,0].lines[0].set_xdata(np.real(u_compl)); axs[1,0].lines[1].set_xdata(np.real(u_versor))
axs[1,1].lines[3].set_ydata(np.arctan(ui/ur)+ku*np.pi); axs[1,1].lines[3].set_xdata(ui / ur)
annotations = [child for child in axs[0,0].get_children() if isinstance(child, matplotlib.patches.ConnectionPatch)]
if len(annotations): annotations[0].remove(); annotations[1].remove();
if show_lines:
con = ConnectionPatch(xyA=xyP, xyB=xyI, axesA=axs[0,0], axesB=axs[0,1],**anno_args); axs[0,0].add_artist(con)
con = ConnectionPatch(xyA=xyP, xyB=xyR, axesA=axs[0,0], axesB=axs[1,0],**anno_args); axs[0,0].add_artist(con)
axs[1,0].set_xlim(axs[0,0].get_xlim()); axs[0,1].set_ylim(axs[0,0].get_ylim())
```
%% 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.
......