Commit 5eedc20e authored by Nicolas Ewald Alfons Horst's avatar Nicolas Ewald Alfons Horst
Browse files

initial commit

parents
Pipeline #360324 passed with stage
in 3 minutes and 17 seconds
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# C extensions
*.so
# Jupyter
.ipynb_checkpoints
image: docker:19.03.1
services:
- docker:19.03.1-dind
stages:
- build
variables:
GIT_SUBMODULE_STRATEGY: recursive
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_HOST: tcp://docker:2376 # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
before_script:
- echo ${CI_REGISTRY}
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
- echo ${CI_CE_REGISTRY}
- docker login -u ${CI_CE_REGISTRY_USER} -p ${CI_CE_REGISTRY_TOKEN} ${CI_CE_REGISTRY}
build:
stage: build
script:
- docker pull ${CI_REGISTRY_IMAGE}:latest || true
- docker build --cache-from ${CI_REGISTRY_IMAGE}:latestci
--tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
--tag ${CI_REGISTRY_IMAGE}:latest .
- docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG}
- docker push ${CI_REGISTRY_IMAGE}:latest
only:
- master
only:
changes:
- binder/*
- Dockerfile
[submodule "ient_nb"]
path = ient_nb
url = https://github.com/IENT/ient.nb.git
ARG BASE_IMAGE=registry.git.rwth-aachen.de/jupyter/profiles/rwth-courses
FROM ${BASE_IMAGE}
RUN conda install --quiet --yes \
'scipy==1.4.1' && \
conda clean --all
# Copy workspace
COPY ./ /home/jovyan
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"lines_to_next_cell": 0
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": false,
"jupyter": {
"source_hidden": true
}
},
"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"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"hide_input": false,
"jupyter": {
"RWTH_LANG": "EN",
"source_hidden": true
},
"lines_to_next_cell": 2
},
"outputs": [],
"source": [
"# default for english language\n",
"_ = lambda s: s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div>\n",
" <img src=\"figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
"</div>"
]
},
{
"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 <span class=\"fa-chevron-right fa\"></span> 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
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"lines_to_next_cell": 0
},
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"# Copyright 2020 Institut für Nachrichtentechnik, RWTH Aachen University\n",
"%matplotlib widget\n",
"from ipywidgets import interact, interactive\n",
"import ipywidgets as widgets\n",
"from IPython.display import clear_output, display, HTML\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from scipy import signal\n",
"\n",
"import rwth_nb.plots.mpl_decorations as rwth_plots\n",
"from rwth_nb.misc.signals import *\n",
"\n",
"# tau-axis\n",
"(tau,deltat) = np.linspace(-20, 20, 4001, retstep=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div>\n",
" <img src=\"figures/rwth_ient_logo@2x.png\" style=\"float: right;height: 5em;\">\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {
"RWTH_LANG": "EN",
"lines_to_next_cell": 0
},
"source": [
"# Example for Calculating the Convolution Integral\n",
"To start: In the menu: Run <span class=\"fa-chevron-right fa\"></span> Select Run All Cells.\n",
"## Introduction\n",
"The convolution integral is defined as"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$g(t) \n",
"= s(t)\\ast h(t)\n",
"= \\int\\limits_{-\\infty}^{\\infty} s(\\tau) h(t-\\tau) \\mathrm{d}\\tau\\text{ .}$$\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"RWTH_LANG": "EN",
"lines_to_next_cell": 0
},
"source": [
"## Derivation\n",
"### Input Signal and Impulse Response\n",
"As shown in section 1.6 of the script, here the convolution is calculated using the impulse response of the $RC$ system"
]
},
{
"cell_type": "markdown",
"metadata": {
"lines_to_next_cell": 0
},
"source": [
"$$h(t) = \\frac{1}{T}\\varepsilon(t)\\mathrm{e}^{-t/T}$$ "
]
},
{
"cell_type": "markdown",
"metadata": {
"RWTH_LANG": "EN",
"lines_to_next_cell": 0
},
"source": [
"is shown with $T=RC$. Its reaction to a rectangular pulse of duration $T_0$ and amplitude $a$"
]
},
{
"cell_type": "markdown",
"metadata": {
"lines_to_next_cell": 0
},
"source": [
"$$s(t) = a\\;\\mathrm{rect}\\left(\\frac{t-T_0/2}{T_0}\\right)$$"
]
},
{
"cell_type": "markdown",
"metadata": {
"RWTH_LANG": "EN"
},
"source": [
"shall be examined. Both functions are shown in the following figure."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Input signal\n",
"T0 = 4 # duration of rect\n",
"a = 1/4 # amplitude of rect\n",
"s = lambda t: a*rect((t-T0/2)/T0) # Rect impuls with duration T0 and amplitude a\n",
"\n",
"# Impulse response h(t) of RC system\n",
"T = 2\n",
"h = lambda t: 1/T*unitstep(t)*np.exp(-t/T) # RC system with T=R*C"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"# Plot both signals\n",
"fig,ax = plt.subplots(1,1); ax.plot(tau, h(tau), 'rwth:blue'); ax.plot(tau, s(tau), 'rwth:green'); \n",
"ax.set_xlabel(r'$\\rightarrow \\tau$'); ax.set_xlim([-11,11]); ax.set_ylim([-0.05,0.55]); rwth_plots.axis(ax);\n",
"ax.text(T/4, 1/T, r'$h(\\tau)$', color='rwth:blue', fontsize=12);\n",
"ax.text(T0, a, r'$s(\\tau)$', color='rwth:green', fontsize=12); "
]
},
{
"cell_type": "markdown",
"metadata": {
"RWTH_LANG": "EN"
},
"source": [
"### Derivation Convolution Integral\n",
"\n",
"\n",
"$h(\\tau)$ is first mirrored, the resulting signal is $h(-\\tau)$."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"fig,ax = plt.subplots(1,1); ax.plot(tau, h(-tau), 'rwth:blue'); \n",
"ax.set_xlabel(r'$\\rightarrow \\tau$'); ax.set_ylabel(r'$\\uparrow h(-\\tau)$'); \n",
"ax.set_xlim([-11,11]); ax.set_ylim([-0.05,0.55]); rwth_plots.axis(ax);"
]
},
{
"cell_type": "markdown",
"metadata": {
"RWTH_LANG": "EN"
},
"source": [
"The mirrored version $h(-\\tau)$ is shifted by $t$, where $t$ can have both positive and negative values."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"jupyter": {
"source_hidden": true
}
},
"outputs": [],
"source": [
"fig,ax = plt.subplots(1,1); \n",
"\n",
"t = 2\n",
"ax.plot(tau, h(t-tau), 'rwth:blue'); \n",
"rwth_plots.annotate_xtick(ax, r'$t>0$', t, -0.05, 'rwth:blue')\n",
"\n",
"t = -3\n",