DataAnalysis2021/05-Spectrogram/nonlinear_thresholding.ipynb
Janis Heuel a47d87bc9b Add all notebooks for part ii of the lecture. (#13)
Reviewed-on: #13
Co-authored-by: Janis Heuel <janis.heuel@ruhr-uni-bochum.de>
Co-committed-by: Janis Heuel <janis.heuel@ruhr-uni-bochum.de>
2021-06-26 16:15:46 +02:00

166 lines
4.9 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Nonlinear Thresholding\n",
"When noise and signal share a common frequency band, spectral filtering would lead to a loss in signal. For these cases, we need different techniques to reduce the disturibing noise. We start with a reocorde signal $x(t)$, contains some signal $s(t)$ and additive noise $n(t)$:\n",
"$$\n",
"x(t) = s(t) + n(t)\n",
"$$\n",
"We can rewrite the equation above in time-frequency domain as\n",
"$$\n",
"X(t, f) = S(t, f) + N(t, f) ~.\n",
"$$\n",
"Assuming that some time-frequnecy coefficients can be associated by noise, we set all coefficients, which a below this threshold, to zero:\n",
"$$\n",
"\\tilde{X}(t, f) = \\left\\{\n",
" \\begin{array}{@{}ll@{}}\n",
" X(t, f) & \\mathrm{if}~ |X(t, f)| \\geq \\beta(f) \\\\\n",
" 0 & \\mathrm{otherwise}\n",
" \\end{array}\\right.\n",
" ~,\n",
"$$\n",
"where $\\beta(f)$ denotes the threshold function. The threshold function is defined as \n",
"$$\n",
"\\beta(f) = \\mathrm{ECDF}_f^{-1} (P = 0.99) ~,\n",
"$$\n",
"where $\\mathrm{ECDF}_f^{-1}$ denotes the inverse cumulative distribution function or quantile function, e.g. before the first arrival of earthquake waves."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Load all required packages\n",
"import os\n",
"import numpy as np\n",
"from scipy.signal import stft, istft\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Load our earthquake data and plot\n",
"d = np.load(os.path.join(os.path.expanduser('~'),'work', 'data', 'events', 'bug2019mgoh_Z.npz'))\n",
"#d = np.load(os.path.join(os.path.expanduser('~'),'work', 'data', 'events', 'bug2019gbbo_Z.npz'))\n",
"#d = np.load(os.path.join(os.path.expanduser('~'),'work', 'data', 'events', 'bug2019ibsd_Z.npz'))\n",
"plt.figure(figsize=(15, 8))\n",
"plt.plot(d['data']);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Compute spectrogram of data\n",
"f, t, X = stft(d['data'], fs=1/0.01, nfft=198, nperseg=99) # Be careful with choice of nfft and nperseg, \n",
" # because istft does not work for all pairs\n",
"print(X.shape)\n",
"plt.figure(figsize=(15, 8))\n",
"plt.pcolormesh(t, f, np.abs(X))\n",
"plt.xlabel(\"Frequency (Hz)\")\n",
"plt.ylabel(\"Time (s)\");"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Functions for thresholding\n",
"def threshold(X, quantile=0.99):\n",
" \"\"\"\n",
" X: time-frequency coefficients\n",
" q: quantile [0-1]\n",
" \"\"\"\n",
" # Loop over frequencies to build threshold function\n",
" beta = np.zeros(X.shape[0])\n",
" for i in range(X.shape[0]):\n",
" beta[i] = np.quantile(np.abs(X[i, :]), q=quantile)\n",
" \n",
" return beta\n",
"\n",
"def modify_spectrogram(X, beta):\n",
" # Loop over all items in X and apply threshold\n",
" # Task: modify X!\n",
" \n",
" return X"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Compute STFT of data before first arrival of P\n",
"_, _, X_thres = stft(d['data'][:2500], fs=1/0.01, nfft=198, nperseg=99)\n",
"# Estimate threshold fucntion\n",
"beta = threshold(X_thres)\n",
"\n",
"# Modifiy original spectrogram\n",
"X_mod = modify_spectrogram(X, beta)\n",
"\n",
"# Plot modified spectrogram\n",
"plt.figure(figsize=(15, 8))\n",
"plt.pcolormesh(t, f, np.abs(X_mod))\n",
"plt.xlabel(\"Frequency (Hz)\")\n",
"plt.ylabel(\"Time (s)\");"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Inverse STFT of modified spectrogram\n",
"t, x_mod = istft(X_mod, fs=1/0.01, nfft=198, nperseg=99)\n",
"\n",
"# Plot corrected seismogram\n",
"plt.figure(figsize=(15, 8))\n",
"plt.plot(t, x_mod);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.6.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}