Verified Commit 3bc2b6df authored by Christian Rohlfing's avatar Christian Rohlfing
Browse files

Tight axis for GUI in convolution example

parent 5940beec
%% 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 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))
fig, axs = plt.subplots(2, 1, figsize=(8,6)); fig.tight_layout();
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.
......
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