{ "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 }