m-thesis-introduction/simulations/06_correlation_single_sine_gauss.ipynb

564 lines
111 KiB
Text
Raw Normal View History

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Discrete Sine + Delta correlation\n",
"\n",
"Bandpass a delta peak, and try to correlate it with an appropriate sine wave.\n",
"\\\n",
"Show that we can lift the degeneracy in the correlations (within a window)."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import scipy.fft as ft\n",
"import scipy.signal as signal\n",
"\n",
"# monkey patch correlation_lags into signal if it does not exist\n",
"if not hasattr(signal, 'correlation_lags'):\n",
" def correlation_lags(in1_len, in2_len, mode='full'):\n",
" r\"\"\"\n",
" Calculates the lag / displacement indices array for 1D cross-correlation.\n",
" Parameters\n",
" ----------\n",
" in1_size : int\n",
" First input size.\n",
" in2_size : int\n",
" Second input size.\n",
" mode : str {'full', 'valid', 'same'}, optional\n",
" A string indicating the size of the output.\n",
" See the documentation `correlate` for more information.\n",
" See Also\n",
" --------\n",
" correlate : Compute the N-dimensional cross-correlation.\n",
" Returns\n",
" -------\n",
" lags : array\n",
" Returns an array containing cross-correlation lag/displacement indices.\n",
" Indices can be indexed with the np.argmax of the correlation to return\n",
" the lag/displacement.\n",
" Notes\n",
" -----\n",
" Cross-correlation for continuous functions :math:`f` and :math:`g` is\n",
" defined as:\n",
" .. math::\n",
" \\left ( f\\star g \\right )\\left ( \\tau \\right )\n",
" \\triangleq \\int_{t_0}^{t_0 +T}\n",
" \\overline{f\\left ( t \\right )}g\\left ( t+\\tau \\right )dt\n",
" Where :math:`\\tau` is defined as the displacement, also known as the lag.\n",
" Cross correlation for discrete functions :math:`f` and :math:`g` is\n",
" defined as:\n",
" .. math::\n",
" \\left ( f\\star g \\right )\\left [ n \\right ]\n",
" \\triangleq \\sum_{-\\infty}^{\\infty}\n",
" \\overline{f\\left [ m \\right ]}g\\left [ m+n \\right ]\n",
" Where :math:`n` is the lag.\n",
" Examples\n",
" --------\n",
" Cross-correlation of a signal with its time-delayed self.\n",
" >>> from scipy import signal\n",
" >>> from numpy.random import default_rng\n",
" >>> rng = default_rng()\n",
" >>> x = rng.standard_normal(1000)\n",
" >>> y = np.concatenate([rng.standard_normal(100), x])\n",
" >>> correlation = signal.correlate(x, y, mode=\"full\")\n",
" >>> lags = signal.correlation_lags(x.size, y.size, mode=\"full\")\n",
" >>> lag = lags[np.argmax(correlation)]\n",
" \"\"\"\n",
"\n",
" # calculate lag ranges in different modes of operation\n",
" if mode == \"full\":\n",
" # the output is the full discrete linear convolution\n",
" # of the inputs. (Default)\n",
" lags = np.arange(-in2_len + 1, in1_len)\n",
" elif mode == \"same\":\n",
" # the output is the same size as `in1`, centered\n",
" # with respect to the 'full' output.\n",
" # calculate the full output\n",
" lags = np.arange(-in2_len + 1, in1_len)\n",
" # determine the midpoint in the full output\n",
" mid = lags.size // 2\n",
" # determine lag_bound to be used with respect\n",
" # to the midpoint\n",
" lag_bound = in1_len // 2\n",
" # calculate lag ranges for even and odd scenarios\n",
" if in1_len % 2 == 0:\n",
" lags = lags[(mid-lag_bound):(mid+lag_bound)]\n",
" else:\n",
" lags = lags[(mid-lag_bound):(mid+lag_bound)+1]\n",
" elif mode == \"valid\":\n",
" # the output consists only of those elements that do not\n",
" # rely on the zero-padding. In 'valid' mode, either `in1` or `in2`\n",
" # must be at least as large as the other in every dimension.\n",
"\n",
" # the lag_bound will be either negative or positive\n",
" # this let's us infer how to present the lag range\n",
" lag_bound = in1_len - in2_len\n",
" if lag_bound >= 0:\n",
" lags = np.arange(lag_bound + 1)\n",
" else:\n",
" lags = np.arange(lag_bound, 1)\n",
" return lags\n",
"\n",
" signal.correlation_lags = correlation_lags"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def plot_spectrum( ax, spectrum, freqs, plot_complex=False, plot_power=False, plot_amplitude=None):\n",
" \"\"\" Plot a signal's spectrum on an Axis object\"\"\"\n",
" plot_amplitude = plot_amplitude or (not plot_power and not plot_complex)\n",
" alpha = 1\n",
" \n",
" ax.set_title(\"Spectrum\")\n",
" ax.set_xlabel(\"f (Hz)\")\n",
" ylabel = \"\"\n",
" if plot_amplitude or plot_complex:\n",
" ylabel = \"Amplitude\"\n",
" if plot_power:\n",
" if ylabel:\n",
" ylabel += \"|\"\n",
" ylabel += \"Power\"\n",
" ax.set_ylabel(ylabel)\n",
"\n",
" if plot_complex:\n",
" alpha = 0.5\n",
" ax.plot(freqs, np.real(spectrum), '.-', label='Real', alpha=alpha)\n",
" ax.plot(freqs, np.imag(spectrum), '.-', label='Imag', alpha=alpha)\n",
"\n",
" if plot_power:\n",
" ax.plot(freqs, np.abs(spectrum)**2, '.-', label='Power', alpha=alpha)\n",
" \n",
" if plot_amplitude:\n",
" ax.plot(freqs, np.abs(spectrum), '.-', label='Abs', alpha=alpha)\n",
"\n",
" ax.legend()\n",
"\n",
" return ax\n",
"\n",
"def fft_bandpass(signal, band, samplerate):\n",
" \"\"\"\n",
" Simple bandpassing function employing a FFT.\n",
"\n",
" Parameters\n",
" ----------\n",
" signal : arraylike\n",
" band : tuple(low, high)\n",
" Frequencies for bandpassing\n",
" samplerate : float\n",
" \"\"\"\n",
" signal = np.asarray(signal)\n",
"\n",
" fft = ft.rfft(signal)\n",
" freqs = ft.rfftfreq(signal.size, 1/samplerate)\n",
" fft[(freqs < band[0]) | (freqs > band[1])] = 0\n",
" \n",
" return ft.irfft(fft, signal.size), (fft, freqs)\n",
"\n",
"def deltapeak(timelength=1e3, samplerate=1, offset=None, peaklength=1):\n",
" N_samples = int(timelength * samplerate)\n",
" if offset is None:\n",
" offset = (np.random.random()*N_samples).astype(int) % N_samples\n",
" \n",
" position = (offset + np.arange(0, peaklength)).astype(int) % N_samples\n",
" \n",
" signal = np.zeros(N_samples)\n",
" signal[position] = 1\n",
" \n",
" return signal, position\n",
"\n",
"def sin_delay(f, t, t_delay=0, phase=0):\n",
" return np.cos(2*np.pi*f * (t - t_delay) + phase)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generate a delta peak and bandpass it"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Size: 25; Offset: 0; PeakLength: 1\n"
]
}
],
"source": [
"# Generate a delta peak and bandpass it\n",
"samplerate = 500 # MHz\n",
"band = (30, 80) # MHz\n",
"\n",
"us = 1e3 # ns\n",
"ns = 1/us # us\n",
"\n",
"## Delta peak properties\n",
"imp_timelength = 50 * ns# ns\n",
"imp_peaklength = 1\n",
"imp_time = np.arange(0, imp_timelength, 1/samplerate)\n",
"imp_offset = [1400]\n",
"\n",
"orig_imp, imp_offset = deltapeak(imp_timelength, samplerate, offset=imp_offset, peaklength=imp_peaklength)\n",
"\n",
"## Bandpass it\n",
"imp, (fft, fft_freqs) = fft_bandpass(orig_imp, band, samplerate)\n",
"imp /= np.max(imp)\n",
"\n",
"#\n",
"print(\"Size: {}; Offset: {}; PeakLength: {}\".format(orig_imp.size, imp_offset[0], len(imp_offset)))"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"<ipython-input-4-5b3a8514ce9c>:22: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.\n",
" fig.show()\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 1152x288 with 2 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"# Plot timedomain and frequency domain of the bandpassed signal\n",
"fig, (ax2, ax1) = plt.subplots(1,2, figsize=(16,4),sharey=True)\n",
"## Spectrum\n",
"plot_spectrum(ax1, fft, fft_freqs)\n",
"ax1.set_xlabel(\"Frequency [MHz]\")\n",
"ax1.grid(True)\n",
"ax1.margins(0.1, 0.1)\n",
"ax1.get_legend().remove()\n",
"ax1.set_xlim(0, 200)\n",
"\n",
"## Signal\n",
"ax2.set_title(\"Signal\")\n",
"ax2.margins(0.1, 0.1)\n",
"ax2.set_xlabel('Time [ns]')\n",
"ax2.set_ylabel('Amplitude')\n",
"ax2.grid(True)\n",
"ax2.plot(imp_time/ns, imp, label='Bandpassed')\n",
"ax2.plot(imp_time/ns, orig_imp, label='Original', zorder=-1, color='g')\n",
"ax2.axvline(imp_time[imp_offset[0]]/ns, color='r', ls='--')\n",
"ax2.legend()\n",
"\n",
"fig.show()"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"### correlation\n",
"def correlation_and_lag(sig1, sig2, mode=\"same\", normalise=False):\n",
" corr = signal.correlate(sig1, sig2, mode=mode)\n",
" if normalise:\n",
" corr /= np.max(corr)\n",
"\n",
" lags = signal.correlation_lags(sig1.size, sig2.size, mode=mode)\n",
" \n",
" return corr, lags\n",
"\n",
"def find_best_lag(sig1, sig2, fix_one_short=False, fix_positive=False, **corr_kwargs):\n",
" corr, lags = correlation_and_lag(sig1, sig2, **corr_kwargs)\n",
" \n",
" lag = lags[np.argmax(corr)]\n",
" \n",
" if fix_one_short:\n",
" # for some reason it is always one short\n",
" if lag > 0:\n",
" lag += 1\n",
" elif lag < 0:\n",
" lag -= 1\n",
"\n",
" # turn negative lag into positive\n",
" if fix_positive and lag < 0:\n",
" print(\"negative lag\")\n",
" lag += len(sig2)\n",
" \n",
" return lag, (corr, lags)\n",
"\n",
"\n",
"def find_beacon_phase_delay(samplerate, f_beacon, reference_beacon, delayed_beacon, **lag_kwargs):\n",
" \"\"\"\n",
" Return phase delay of `beacon` with respect to `reference_beacon`.\n",
" Note that the returned value can be off by a multiple of $2\\pi$.\n",
" \n",
" Parameters\n",
" ==========\n",
" samplerate : float\n",
" Samplerate of both reference_beacon and delayed_beacon\n",
" f_beacon : float\n",
" Frequency of the beacons\n",
" reference_beacon : ndarray\n",
" The beacon to use as a reference\n",
" beacon : ndarray\n",
" The beacon to find the delay for\n",
" \"\"\"\n",
" \n",
" calc_lag, _ = find_best_lag(reference_beacon, delayed_beacon, **lag_kwargs)\n",
" \n",
" return 2*np.pi* f_beacon * calc_lag /samplerate \n",
" \n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Correlate a sinusoid with the bandpassed delta peak"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Known offset [ns]: 6.0\n",
"Known phase [ns]: 1.884955592153876\n",
"Expected lag: 3.0\n",
"Lag time multiplier [ns]: 2.0\n",
"Calc Lag: 1\n",
"Calc Lag time [ns]: 2.0\n",
"Phase lag: 0.6283185307179586\n"
]
}
],
"source": [
"###########################################\n",
"# Correlate a sinusoid\n",
"\n",
"## define sinusoid properties\n",
"\n",
"# in-band or out-of-band\n",
"if True:\n",
" f_sine = 50 # MHz\n",
" corr_sig_timelength = 1/f_sine # us\n",
"else:\n",
" f_sine = 20 # MHz\n",
" corr_sig_timelength = 1/f_sine # us\n",
" \n",
"## define general correlation signal properties\n",
"corr_sig_samplerate = samplerate # MHz\n",
"corr_sig_samplelength = corr_sig_timelength * corr_sig_samplerate\n",
"corr_time = np.arange(0, corr_sig_timelength, 1/corr_sig_samplerate)\n",
"\n",
"corr_sig = sin_delay(f_sine, corr_time, t_delay=0, phase=-1/2*np.pi)\n",
"\n",
"## define the signals\n",
"if not True:\n",
" sig1 = imp\n",
" sig1_time = imp_time\n",
" sig1_offset = imp_time[imp_offset[0]]\n",
"else:\n",
" sig1_offset = 6*ns # us\n",
" sig1 = sin_delay(f_sine, corr_time, t_delay=sig1_offset)\n",
" sig1_time = corr_time\n",
"\n",
"\n",
"## correlate it and find the best correlation\n",
"calc_lag, (corr, lags) = find_best_lag(sig1, corr_sig, mode='full', fix_one_short=False)\n",
"\n",
"calc_lag += 1\n",
"\n",
"#####\n",
"lag_times = lags / corr_sig_samplerate # us\n",
"calc_lag_time = (calc_lag) / corr_sig_samplerate # us\n",
"\n",
"\n",
"\n",
"#(calc_lag_time - 1/corr_sig_samplerate)\n",
"#((calc_lag_time*corr_sig_samplerate - 1) - (calc_lag_time - 1)) /samplerate\n",
"\n",
"\n",
"\n",
"\n",
"#calc_lag_time = ((len(corr)-1)/2 - corr.argmax())/corr_sig_samplerate\n",
"\n",
"calc_phase_lag = 2*np.pi*f_sine*calc_lag_time\n",
"\n",
"print(\"Known offset [ns]:\", sig1_offset/ns)\n",
"print(\"Known phase [ns]:\", 2*np.pi*f_sine*sig1_offset)\n",
"print(\"Expected lag:\", sig1_offset*corr_sig_samplerate)\n",
"print(\"Lag time multiplier [ns]:\", 1/corr_sig_samplerate/ns)\n",
"print(\"Calc Lag:\", calc_lag)\n",
"print(\"Calc Lag time [ns]:\", calc_lag_time/ns)\n",
"print(\"Phase lag:\", calc_phase_lag)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2.0\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"<ipython-input-7-42b7d03bc798>:26: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.\n",
" fig.show();\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"#####\n",
"# Plot signal\n",
"#####\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.set_xlabel(\"Time [ns]\")\n",
"ax.set_ylabel(\"Amplitude\")\n",
"\n",
"\n",
"ax.plot(sig1_time/ns, sig1+2, label='Signal')\n",
"ax.axvline(sig1_offset/ns, color='r', ls='--', label='offset')\n",
"\n",
"\n",
"ax.axvline(calc_lag_time/ns, color='b', ls=(2, (10, 10)), label='calc offset')\n",
"ax.plot(corr_time/ns, corr_sig+2, label=\"Uncorr\")\n",
"ax.plot(sig1_time/ns, sin_delay(f_sine, sig1_time, t_delay=calc_lag_time), label=\"Corr time\")\n",
"ax.plot(sig1_time/ns, sin_delay(f_sine, sig1_time, phase=-1*calc_phase_lag)-0.2, label=\"Corr phase\")\n",
"\n",
"# debugging\n",
"if True:\n",
" ax.plot(corr_time[-1]/ns + corr_time/ns, sin_delay(f_sine, corr_time, t_delay=sig1_offset)+2, label=\"Cheat time\")\n",
" ax.plot(corr_time[-1]/ns + corr_time/ns, sin_delay(f_sine, corr_time, phase=-2*np.pi*sig1_offset*f_sine)+2, label=\"Cheat phase\")\n",
" \n",
" \n",
"ax.legend()\n",
"fig.show();\n",
"print((sig1_offset - calc_lag_time)*samplerate)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"<ipython-input-8-b80dbc5f3c93>:20: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.\n",
" fig.show();\n"
]
},
{
"data": {
"image/png": "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
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"#####\n",
"# Plot Correlation\n",
"#####\n",
"max_corr_id = np.argmax(corr)\n",
"min_corr_id = np.argmin(corr)\n",
"fig, ax = plt.subplots()\n",
"ax.set_xlabel(\"Lag [ns]\")\n",
"ax.set_ylabel(\"Correlation\")\n",
"ax.plot(lag_times/ns, corr)\n",
"\n",
"ax.plot()\n",
"\n",
"ax.axvline(lag_times[max_corr_id]/ns, ls='--',color='g', label=\"max_corr\")\n",
"ax.axhline(corr[max_corr_id], ls='--', color='g')\n",
"ax.axvline(lag_times[min_corr_id]/ns, ls='--', color='r', label='min_corr')\n",
"ax.axhline(corr[min_corr_id], ls='--', color='r')\n",
"\n",
"ax.axvline(calc_lag_time/ns, ls=(0, (5, 5)), color='purple', label='calculated')\n",
"ax.legend()\n",
"fig.show();"
]
}
],
"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",
"version": "3.10.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}