Commit c8904836 by Nicolas Ewald Alfons Horst

### Revert "initial commit"

This reverts commit 2407c166.
parent 2407c166
Pipeline #360416 passed with stage
in 2 minutes and 52 seconds
 { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": false, "jupyter": { "source_hidden": true }, "lines_to_next_cell": 2 }, "outputs": [], "source": [ "# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University\n", "%matplotlib widget\n", "import ipywidgets as widgets\n", "from ipywidgets import interact, interactive\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import scipy as sp\n", "import scipy.special\n", "import scipy.signal\n", "\n", "import rwth_nb.plots.mpl_decorations as rwth_plots\n", "from rwth_nb.misc.signals import *\n", "\n", "# language settings\n", "_ = lambda s: s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " \n", "
" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN", "lines_to_next_cell": 0 }, "source": [ "# Auto and Cross correlation function of energy signals\n", "To start: In the menu: Run Select Run All Cells. \n", "## Introduction\n", "\n", "### Energy Signal\n", "\n", "A signal $s(t)$ is called energy signal when its signal energy is finite, so" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$E_s = \\int\\limits_{-\\infty}^\\infty |s(t)|^2 \\mathrm{d} t < \\infty \\text{ .}$$ " ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN", "lines_to_next_cell": 0 }, "source": [ "Many important signals do not have a finite total energy, e.g. all periodic signals, the step function or random signals that are not limited in time. For signals with Dirac pulses the energy is not defined.\n", "\n", "### Cross Correlation Function\n", "For two energy signals $s(t)$ and $g(t)$, the *cross correlation function* can be calculated. This shows how similar two signals are at different displacements $\\tau$." ] }, { "cell_type": "markdown", "metadata": { "lines_to_next_cell": 0 }, "source": [ "$$\n", "\\varphi_{sg}^\\mathrm{E}(\\tau) \n", "= \\int\\limits_{-\\infty}^\\infty s^\\ast(t) g(t+\\tau)\\mathrm{d}t \n", "\\stackrel{t\\rightarrow -t}{=} \\int\\limits_{-\\infty}^\\infty s(-t)^\\ast g(\\tau-t) \\mathrm{d} t \n", "= s^\\ast(-\\tau) \\ast g(\\tau)\n", "= \\left[\\varphi_{gs}^\\mathrm{E}(-\\tau)\\right]^\\ast\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN", "lines_to_next_cell": 0 }, "source": [ "The cross-correlation functions $\\varphi_{sg}^\\mathrm{E}(\\tau)$ and $\\varphi_{gs}^\\mathrm{E}(\\tau)$ are therefore time-mirrored and complex-conjugated to each other.\n", "For the calculation of the cross correlation function, the two signals do not necessarily have to be energy signals, it is sufficient that the integral can be calculated. Note here also the similarity to the convolution of two signals, the calculation can be done accordingly.\n", "### Autocorrelation Function\n", "\n", "The autocorrelation function corresponds to the cross-correlation function when $g(t) = s(t)$ applies. It shows how similar a signal is to itself in case of a time shift $\\tau$." ] }, { "cell_type": "markdown", "metadata": { "lines_to_next_cell": 0 }, "source": [ "$$\n", "\\varphi_{ss}^\\mathrm{E}(\\tau) \n", "= \\int\\limits_{-\\infty}^\\infty s^\\ast(t) s(t+\\tau)\\mathrm{d}t \\text{.}\n", "$$" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN", "lines_to_next_cell": 0 }, "source": [ "The autocorrelation function has the following general properties:\n", "* The autocorrelation function is always an even function.\n", "* An autocorrelation function takes the maximum value for $\\tau=0$, because in this case there is the greatest similarity.\n", "* The maximum of the autocorrelation function of an energy signal is equal to its energy" ] }, { "cell_type": "markdown", "metadata": { "lines_to_next_cell": 0 }, "source": [ "$$\\varphi_{ss}^\\mathrm{E}(0)=E_s \\text{.}$$" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN", "lines_to_next_cell": 0 }, "source": [ "* In the case of time-limited signals, the autocorrelation function has twice the width of the signal.\n", "\n", "\n", "## Interactive Demo\n", "The interactive demo allows you to view cross and autocorrelation for different signals." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$\n", "\\varphi_{sg}^\\mathrm{E}(\\tau) \n", "= s^\\ast(-\\tau) \\ast g(\\tau) \n", "= g(\\tau) \\ast s^\\ast(-\\tau)\n", "= \\int\\limits_{-\\infty}^\\infty g(t) s^\\ast(t-\\tau) \\mathrm{d} t \n", "$$" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN" }, "source": [ "It is also possible to define a custom function $s_0(t)$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s_0 = lambda t: rect(t/2-1/2)*(-t)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "jupyter": { "source_hidden": true } }, "outputs": [], "source": [ "def correlation(s, g):\n", " # Correlate s and g numerically\n", " return sp.signal.convolve(np.conj(s(-t)),g(t), mode='full')*deltat\n", "\n", "fs = 2000 # Samplingrate\n", "(t,deltat) = np.linspace(-8,8, 16*fs, retstep=True) # Zeitachse\n", "(tau,deltatau) = np.linspace(-16,16, 2*len(t)-1, retstep=True) # Korrelation\n", "\n", "signal_types = {_('rectangle' ): rect,\n", " _('triangle' ): tri, \n", " _('step function' ): unitstep, \n", " _('si-function' ): lambda t: si(t*np.pi), \n", " _('exponential pulse' ): lambda t: unitstep(t)*np.exp(-t),\n", " _('Gauss signal' ): gauss, \n", " _('double rectangle' ): lambda t: rect(t*2+0.5)-rect(t*2-0.5),\n", " _('ramp' ): lambda t: t*rect(t-0.5), \n", " _('shifted rectangle' ): lambda t: -rect(t-0.5),\n", " _('own creation' ): s_0,\n", " }" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN" }, "source": [ "Select signals for $s(t)$ and $g(t)$ from the drop-down menu. For both signals the width $T$ and the offset $t_0$ can also be adjusted. The respective signals are then displayed in the figure below." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": false, "jupyter": { "source_hidden": true } }, "outputs": [], "source": [ "fig0, axs0 = plt.subplots(1, 2, figsize=(8,2))\n", "@widgets.interact(s_type=widgets.Dropdown(options=list(signal_types.keys()), description=_('choose')+r' $s(t)$:'),\n", " s_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=_('scaling')+r' T', style=rwth_plots.wdgtl_style), \n", " s_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=_('shift')+r' $t_0$', style=rwth_plots.wdgtl_style), \n", " g_type=widgets.Dropdown(options=list(signal_types.keys()), description=_('choose')+r' $g(t)$:'),\n", " g_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=_('scaling')+r' T', style=rwth_plots.wdgtl_style), \n", " g_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=_('shift')+r' $t_0$', style=rwth_plots.wdgtl_style))\n", "def update_signals(s_type, s_T, s_t0, g_type, g_T, g_t0):\n", " global s, g, phi_sg # reused in second interactive plot\n", " s = lambda t: signal_types[s_type]((t-s_t0)/s_T);\n", " g = lambda t: signal_types[g_type]((t-g_t0)/g_T);\n", " phi_sg = correlation(s, g) # numerical correlation\n", " \n", " if not axs0[0].lines: # plot s(t) and g(t)\n", " ax = axs0[0]; ax.plot(t, s(t), 'rwth:blue');\n", " ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow s(t)$')\n", " ax.set_xlim([-2.9, 2.9]); ax.set_ylim([-1.19, 1.19]); rwth_plots.axis(ax); rwth_plots.grid(ax);\n", " \n", " ax = axs0[1]; ax.plot(t, g(t), 'rwth:blue');\n", " ax.set_xlabel(r'$\\rightarrow t$'); ax.set_ylabel(r'$\\uparrow g(t)$')\n", " ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); rwth_plots.axis(ax); rwth_plots.grid(ax);\n", " else: # update lines\n", " axs0[0].lines[0].set_ydata(s(t)); \n", " axs0[1].lines[0].set_ydata(g(t));\n", " try: # if convolution figure is already opened, update s(t)\n", " if axs[0].lines:\n", " axs[0].lines[0].set_ydata((g(t)));\n", " rwth_plots.update_ylim(axs[0], np.concatenate((g(t), s(t))), 0.19, 5); rwth_plots.update_ylim(axs[1], phi_sg, 0.19, 5);\n", " update_plot(-2); # update correlation plot\n", " except: pass\n", " rwth_plots.update_ylim(axs0[0], s(t), 0.19, 5); rwth_plots.update_ylim(axs0[1], g(t), 0.19, 5); " ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN" }, "source": [ "In the following diagram, the result of the cross-correlation function can now be viewed for the two functions selected above. For this purpose, the slider must be moved from left to right. If the box at integrand is ticked, the currently overlapping area of the two functions is shown dashed. This corresponds to the value of the cross correlation function. This can be viewed interactively in the lower part of the graph." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "hide_input": false, "jupyter": { "source_hidden": true } }, "outputs": [], "source": [ "fig, axs=plt.subplots(2, 1, figsize=(8, 8 / rwth_plots.fig_aspect))\n", "@widgets.interact(tau_shft=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description=_('shift')+r' $\\tau$', style=rwth_plots.wdgtl_style), \n", " show_integrand=widgets.Checkbox(value=True, description=_('show integrand'), style=rwth_plots.wdgtl_style))\n", "def update_plot(tau_shft, show_integrand=True):\n", " tau_ind = np.where(tau>=tau_shft); tau_ind = tau_ind[0][0]; phi_plot = phi_sg.copy(); phi_plot[tau_ind:] = np.nan; # hide g(t') with t'>t\n", " sg = np.conj(s(t-tau_shft))*g(t) # integrand\n", " \n", " if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time\n", " ax = axs[0]; ax.plot(t, g(t), 'rwth:blue', label=r'$g(t)$'); # plot g(t)\n", " ax.plot(t, np.conj(s(t-tau_shft)), 'rwth:green', label=r'$s^\\ast(t-\\tau)$'); # plot s(t-tau)\n", " ax.plot(t, sg, '--', color='rwth:orange', lw=1, label=r'$g(t)s^\\ast(t-\\tau)$'); # plot integrand\n", " rwth_plots.annotate_xtick(ax, r'$\\tau$', tau_shft, -0.1, 'rwth:blue', 15); # mark t on tau axis\n", " ax.fill_between(t, 0, sg, facecolor=\"none\", hatch=\"//\", edgecolor='rwth:black', linewidth=0.0); # hatch common area\n", " ax.set_xlabel(r'$\\rightarrow t$');\n", " ax.set_xlim([-4.2,4.2]); rwth_plots.update_ylim(ax, np.concatenate((g(t), s(t))), 0.19, 5);\n", " ax.legend(); rwth_plots.axis(ax); rwth_plots.grid(ax); \n", " \n", " ax = axs[1]; ax.plot(tau, phi_plot); # plot phi_sg(tau)\n", " ax.plot([tau_shft, tau_shft], [0, phi_sg[tau_ind]], 'ko--', lw=1);\n", " ax.set_xlabel(r'$\\rightarrow \\tau$'); \n", " ax.set_ylabel(r'$\\uparrow \\varphi_{sg}^\\mathrm{E}(\\tau) = \\int g(t) s^\\ast(t-\\tau)\\mathrm{d}t$'); \n", " ax.set_xlim(axs[0].get_xlim()); rwth_plots.update_ylim(ax, phi_sg, 0.19, 5); \n", " rwth_plots.axis(ax); rwth_plots.grid(ax); fig.tight_layout(); \n", " \n", " else: # Replace only xdata and ydata since plt.plot() takes longer time\n", " ax = axs[0]; ax.lines[1].set_ydata(np.conj(s(t-tau_shft))); ax.lines[2].set_ydata(sg); # update signals\n", " ax.texts[0].set_x(tau_shft); ax.lines[3].set_xdata([tau_shft,tau_shft]) # update labels\n", " if ax.collections: ax.collections[0].remove(); # update integrand\n", " if show_integrand: ax.fill_between(t,0,sg, facecolor=\"none\", hatch=\"//\", edgecolor='rwth:black', linewidth=0.0);\n", " ax = axs[1]; ax.lines[0].set_ydata(phi_plot); # update signals\n", " ax.lines[1].set_xdata([tau_shft, tau_shft]); ax.lines[1].set_ydata([0, phi_sg[tau_ind]]); # update labels\n", "\n", " axs[0].lines[2].set_visible(show_integrand)" ] }, { "cell_type": "markdown", "metadata": { "RWTH_LANG": "EN", "lines_to_next_cell": 2 }, "source": [ "## Tasks\n", "* Select two identical functions. Check the above properties of the autocorrelation function. Vary the functions and look at the autocorrelation function of different signals.\n", "* How does the result change when the width of one of the two signals changes?\n", "* Select two different signals and observe where the maximum cross-correlation occurs in these cases. Can you explain why?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "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, 2020, Institut für Nachrichtentechnik, RWTH Aachen University." ] } ], "metadata": {}, "nbformat": 4, "nbformat_minor": 4 }
 --- jupyter: jupytext: cell_metadata_filter: hide_input,jupyter,RWTH_LANG,-all formats: md,ipynb main_language: python text_representation: extension: .md format_name: markdown format_version: '1.2' jupytext_version: 1.6.0 --- python hide_input=false jupyter={"source_hidden": true} # Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University %matplotlib widget import ipywidgets as widgets from ipywidgets import interact, interactive import numpy as np import matplotlib.pyplot as plt import scipy as sp import scipy.special import scipy.signal import rwth_nb.plots.mpl_decorations as rwth_plots from rwth_nb.misc.signals import * # language settings # DE_START import gettext lng = gettext.translation('messages', localedir='locale', languages=['de']) lng.install() _ = lng.gettext # DE_END # EN_START _ = lambda s: s # EN_END 
# Auto- und Kreuzkorrelationsfunktion von Energiesignalen Zum Starten: Im Menü: Run Run All Cells auswählen. ## Einleitung ### Energiesignal Ein Signal $s(t)$ heißt Energiesignal, wenn seine Signalenergie endlich ist, es gilt also # Auto and Cross correlation function of energy signals To start: In the menu: Run Select Run All Cells. ## Introduction ### Energy Signal A signal $s(t)$ is called energy signal when its signal energy is finite, so $$E_s = \int\limits_{-\infty}^\infty |s(t)|^2 \mathrm{d} t < \infty \text{ .}$$ Viele wichtige Signale haben keine endliche Gesamtenergie, z. B. alle periodischen Signale, die Sprungfunktion oder zeitlich nicht begrenzte Zufallssignale. Für Signale mit Dirac-Impulsen ist die Energie nicht definiert. ### Kreuzkorrelationsfunktion Für zwei Energiesignale $s(t)$ und $g(t)$ kann die *Kreuzkorrelationsfunktion* berechnet werden. Diese zeigt an, wie ähnlich sich zwei Signale bei unterschiedlichen Verschiebungen $\tau$ sind. Many important signals do not have a finite total energy, e.g. all periodic signals, the step function or random signals that are not limited in time. For signals with Dirac pulses the energy is not defined. ### Cross Correlation Function For two energy signals $s(t)$ and $g(t)$, the *cross correlation function* can be calculated. This shows how similar two signals are at different displacements $\tau$. $$\varphi_{sg}^\mathrm{E}(\tau) = \int\limits_{-\infty}^\infty s^\ast(t) g(t+\tau)\mathrm{d}t \stackrel{t\rightarrow -t}{=} \int\limits_{-\infty}^\infty s(-t)^\ast g(\tau-t) \mathrm{d} t = s^\ast(-\tau) \ast g(\tau) = \left[\varphi_{gs}^\mathrm{E}(-\tau)\right]^\ast$$ Die Kreuzkorrelationsfunktionen $\varphi_{sg}^\mathrm{E}(\tau)$ und $\varphi_{gs}^\mathrm{E}(\tau)$ sind also zueinander zeitgespiegelt und konjugiert-komplex. Für die Berechnung der Kreuzkorrelationsfunktion müssen die beiden Signale nicht zwingend Energiesignale sein, es ist ausreichend, dass das Integral berechnet werden kann. Man beachte hier auch die Ähnlichkeit zur Faltung zweier Signale, bei der Berechnung kann entsprechend vorgegangen werden. ### Autokorrelationsfunktion Die Autokorrelationsfunktion entspricht der Kreuzkorrelationsfunktion, wenn $g(t) = s(t)$ gilt. Sie zeigt an, wie ähnlich ein Signal sich selber bei einer zeitlichen Verschiebung $\tau$ ist The cross-correlation functions $\varphi_{sg}^\mathrm{E}(\tau)$ and $\varphi_{gs}^\mathrm{E}(\tau)$ are therefore time-mirrored and complex-conjugated to each other. For the calculation of the cross correlation function, the two signals do not necessarily have to be energy signals, it is sufficient that the integral can be calculated. Note here also the similarity to the convolution of two signals, the calculation can be done accordingly. ### Autocorrelation Function The autocorrelation function corresponds to the cross-correlation function when $g(t) = s(t)$ applies. It shows how similar a signal is to itself in case of a time shift $\tau$. $$\varphi_{ss}^\mathrm{E}(\tau) = \int\limits_{-\infty}^\infty s^\ast(t) s(t+\tau)\mathrm{d}t \text{.}$$ Die Autokorrelationsfunktion besitzt folgende allgemeingültige Eigenschaften: * Die Autokorrelationsfunktion ist immer eine gerade Funktion. * Den maximalen Wert nimmt eine Autokorrelationsfunktion für $\tau=0$ an, da in diesem Fall größte Ähnlichkeit vorliegt. * Das Maximum der Autokorrelationsfunktion eines Energiesignals ist gleich seiner Energie The autocorrelation function has the following general properties: * The autocorrelation function is always an even function. * An autocorrelation function takes the maximum value for $\tau=0$, because in this case there is the greatest similarity. * The maximum of the autocorrelation function of an energy signal is equal to its energy $$\varphi_{ss}^\mathrm{E}(0)=E_s \text{.}$$ * Bei zeitlich begrenzten Signalen hat die Autokorrelationsfunktion die doppelte Breite des Signals. ## Interaktive Demo Die interaktive Demo ermöglicht es, sich die Kreuz- und Autokorrelation für verschiedene Signale anzusehen. * In the case of time-limited signals, the autocorrelation function has twice the width of the signal. ## Interactive Demo The interactive demo allows you to view cross and autocorrelation for different signals. $$\varphi_{sg}^\mathrm{E}(\tau) = s^\ast(-\tau) \ast g(\tau) = g(\tau) \ast s^\ast(-\tau) = \int\limits_{-\infty}^\infty g(t) s^\ast(t-\tau) \mathrm{d} t$$ Es ist auch möglich, eine eigene Funktion $s_0(t)$ zu definieren. It is also possible to define a custom function $s_0(t)$. python s_0 = lambda t: rect(t/2-1/2)*(-t)  python jupyter={"source_hidden": true} def correlation(s, g): # Correlate s and g numerically return sp.signal.convolve(np.conj(s(-t)),g(t), mode='full')*deltat fs = 2000 # Samplingrate (t,deltat) = np.linspace(-8,8, 16*fs, retstep=True) # Zeitachse (tau,deltatau) = np.linspace(-16,16, 2*len(t)-1, retstep=True) # Korrelation signal_types = {_('rectangle' ): rect, _('triangle' ): tri, _('step function' ): unitstep, _('si-function' ): lambda t: si(t*np.pi), _('exponential pulse' ): lambda t: unitstep(t)*np.exp(-t), _('Gauss signal' ): gauss, _('double rectangle' ): lambda t: rect(t*2+0.5)-rect(t*2-0.5), _('ramp' ): lambda t: t*rect(t-0.5), _('shifted rectangle' ): lambda t: -rect(t-0.5), _('own creation' ): s_0, }  Wähle Signale für $s(t)$ und $g(t)$ im Drop-Down-Menü aus. Für beide Signale kann auch die Breite $T$ und die Verschiebung $t_0$ angepasst werden. Die jeweiligen Signale werden dann in der nachfolgenden Abbildung angezeigt. Select signals for $s(t)$ and $g(t)$ from the drop-down menu. For both signals the width $T$ and the offset $t_0$ can also be adjusted. The respective signals are then displayed in the figure below. python hide_input=false jupyter={"source_hidden": true} fig0, axs0 = plt.subplots(1, 2, figsize=(8,2)) @widgets.interact(s_type=widgets.Dropdown(options=list(signal_types.keys()), description=_('choose')+r' $s(t)$:'), s_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=_('scaling')+r' T', style=rwth_plots.wdgtl_style), s_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=_('shift')+r' $t_0$', style=rwth_plots.wdgtl_style), g_type=widgets.Dropdown(options=list(signal_types.keys()), description=_('choose')+r' $g(t)$:'), g_T=widgets.FloatSlider(min=0.5, max=4, value=1, step=.1, description=_('scaling')+r' T', style=rwth_plots.wdgtl_style), g_t0=widgets.FloatSlider(min=-2, max=2, value=0, step=.1, description=_('shift')+r' $t_0$', style=rwth_plots.wdgtl_style)) def update_signals(s_type, s_T, s_t0, g_type, g_T, g_t0): global s, g, phi_sg # reused in second interactive plot s = lambda t: signal_types[s_type]((t-s_t0)/s_T); g = lambda t: signal_types[g_type]((t-g_t0)/g_T); phi_sg = correlation(s, g) # numerical correlation if not axs0[0].lines: # plot s(t) and g(t) ax = axs0[0]; ax.plot(t, s(t), 'rwth:blue'); ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow s(t)$') ax.set_xlim([-2.9, 2.9]); ax.set_ylim([-1.19, 1.19]); rwth_plots.axis(ax); rwth_plots.grid(ax); ax = axs0[1]; ax.plot(t, g(t), 'rwth:blue'); ax.set_xlabel(r'$\rightarrow t$'); ax.set_ylabel(r'$\uparrow g(t)$') ax.set_xlim(axs0[0].get_xlim()); ax.set_ylim(axs0[0].get_ylim()); rwth_plots.axis(ax); rwth_plots.grid(ax); else: # update lines axs0[0].lines[0].set_ydata(s(t)); axs0[1].lines[0].set_ydata(g(t)); try: # if convolution figure is already opened, update s(t) if axs[0].lines: axs[0].lines[0].set_ydata((g(t))); rwth_plots.update_ylim(axs[0], np.concatenate((g(t), s(t))), 0.19, 5); rwth_plots.update_ylim(axs[1], phi_sg, 0.19, 5); update_plot(-2); # update correlation plot except: pass rwth_plots.update_ylim(axs0[0], s(t), 0.19, 5); rwth_plots.update_ylim(axs0[1], g(t), 0.19, 5);  In der nachfolgenden Grafik kann für die beiden oben ausgewählten Funktionen nun das Ergebnis der Kreuzkorrelationsfunktion betrachtet werden. Hierfür muss der Schieberegler von links nach rechts geschoben werden. Wenn das Kästchen bei Integrand angeklickt ist, wird die aktuell überlappende Fläche der beiden Funktionen gestrichelt angezeigt. Diese entspricht dem Wert der Kreuzkorrelationsfunktion. Dies kann im unteren Teil der Grafik interaktiv betrachtet werden. In the following diagram, the result of the cross-correlation function can now be viewed for the two functions selected above. For this purpose, the slider must be moved from left to right. If the box at integrand is ticked, the currently overlapping area of the two functions is shown dashed. This corresponds to the value of the cross correlation function. This can be viewed interactively in the lower part of the graph. python hide_input=false jupyter={"source_hidden": true} fig, axs=plt.subplots(2, 1, figsize=(8, 8 / rwth_plots.fig_aspect)) @widgets.interact(tau_shft=widgets.FloatSlider(min=-4, max=4, value=-2, step=.1, description=_('shift')+r' $\tau$', style=rwth_plots.wdgtl_style), show_integrand=widgets.Checkbox(value=True, description=_('show integrand'), style=rwth_plots.wdgtl_style)) def update_plot(tau_shft, show_integrand=True): tau_ind = np.where(tau>=tau_shft); tau_ind = tau_ind[0][0]; phi_plot = phi_sg.copy(); phi_plot[tau_ind:] = np.nan; # hide g(t') with t'>t sg = np.conj(s(t-tau_shft))*g(t) # integrand if not axs[0].lines: # Call plot() and decorate axes. Usually, these functions take some processing time ax = axs[0]; ax.plot(t, g(t), 'rwth:blue', label=r'$g(t)$'); # plot g(t) ax.plot(t, np.conj(s(t-tau_shft)), 'rwth:green', label=r'$s^\ast(t-\tau)$'); # plot s(t-tau) ax.plot(t, sg, '--', color='rwth:orange', lw=1, label=r'$g(t)s^\ast(t-\tau)$'); # plot integrand rwth_plots.annotate_xtick(ax, r'$\tau$', tau_shft, -0.1, 'rwth:blue', 15); # mark t on tau axis ax.fill_between(t, 0, sg, facecolor="none", hatch="//", edgecolor='rwth:black', linewidth=0.0); # hatch common area ax.set_xlabel(r'$\rightarrow t$'); ax.set_xlim([-4.2,4.2]); rwth_plots.update_ylim(ax, np.concatenate((g(t), s(t))), 0.19, 5); ax.legend(); rwth_plots.axis(ax); rwth_plots.grid(ax); ax = axs[1]; ax.plot(tau, phi_plot); # plot phi_sg(tau) ax.plot([tau_shft, tau_shft], [0, phi_sg[tau_ind]], 'ko--', lw=1); ax.set_xlabel(r'$\rightarrow \tau$'); ax.set_ylabel(r'$\uparrow \varphi_{sg}^\mathrm{E}(\tau) = \int g(t) s^\ast(t-\tau)\mathrm{d}t$'); ax.set_xlim(axs[0].get_xlim()); rwth_plots.update_ylim(ax, phi_sg, 0.19, 5); rwth_plots.axis(ax); rwth_plots.grid(ax); fig.tight_layout(); else: # Replace only xdata and ydata since plt.plot() takes longer time ax = axs[0]; ax.lines[1].set_ydata(np.conj(s(t-tau_shft))); ax.lines[2].set_ydata(sg); # update signals ax.texts[0].set_x(tau_shft); ax.lines[3].set_xdata([tau_shft,tau_shft]) # update labels if ax.collections: ax.collections[0].remove(); # update integrand if show_integrand: ax.fill_between(t,0,sg, facecolor="none", hatch="//", edgecolor='rwth:black', linewidth=0.0); ax = axs[1]; ax.lines[0].set_ydata(phi_plot); # update signals ax.lines[1].set_xdata([tau_shft, tau_shft]); ax.lines[1].set_ydata([0, phi_sg[tau_ind]]); # update labels axs[0].lines[2].set_visible(show_integrand)  ## Aufgaben * Wähle zwei gleiche Funktionen aus. Überprüfe die oben angegebenen Eigenschaften der Autokorrelationsfunktion. Variiere hierbei die Funktionen und betrachte die Autokorrelationsfunktion verschiedener Signale. * Wie ändert sich das Ergebnis, wenn die Breite eines der beiden Signale sich ändert? * Wähle zwei verschiedene Signale aus und beobachte, wo in diesen Fällen die maximale Kreuzkorrelation auftritt. Kannst du erklären, warum? ## Tasks * Select two identical functions. Check the above properties of the autocorrelation function. Vary the functions and look at the autocorrelation function of different signals. * How does the result change when the width of one of the two signals changes? * Select two different signals and observe where the maximum cross-correlation occurs in these cases. Can you explain why? --- 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.