solutions for assignments 4 and 5 added
This commit is contained in:
parent
7d6d611f64
commit
9327a231a9
439
assignment_04/fft_sampling_interpol.ipynb
Normal file
439
assignment_04/fft_sampling_interpol.ipynb
Normal file
File diff suppressed because one or more lines are too long
34
assignment_05/acausalFilters.py
Normal file
34
assignment_05/acausalFilters.py
Normal file
@ -0,0 +1,34 @@
|
||||
# -------------------------------------------------------------
|
||||
# Functions for acausal filtering
|
||||
# -------------------------------------------------------------
|
||||
import numpy as np
|
||||
|
||||
def boxcar_lowpass_filter(fc, df, nf):
|
||||
"""
|
||||
Calculates samples of the boxcar lowpass filter transfer function (positive frequencies only)
|
||||
:param fc: corner frequency in Hz
|
||||
:param df: frequency stepping
|
||||
:param nf: number of frequencies
|
||||
"""
|
||||
return np.where(df*np.arange(0, nf) > fc, 0, 1)
|
||||
|
||||
|
||||
def boxcar_highpass_filter(fc, df, nf):
|
||||
"""
|
||||
Calculates samples of the boxcar highpass filter transfer function (positive frequencies only)
|
||||
:param fc: corner frequency in Hz
|
||||
:param df: frequency stepping
|
||||
:param nf: number of frequencies
|
||||
"""
|
||||
return np.where(df*np.arange(0, nf) < fc, 0, 1)
|
||||
|
||||
|
||||
def hann_lowpass_filter(fc, df, nf):
|
||||
"""
|
||||
Calculates samples of the Hann filter transfer function (positive frequencies only)
|
||||
:param fc: corner frequency in Hz
|
||||
:param df: frequency stepping
|
||||
:param nf: number of frequencies
|
||||
"""
|
||||
f = df*np.arange(0, nf)
|
||||
return np.where(f < fc, np.cos(np.pi*f/fc)**2, 0)
|
466
assignment_05/spectral-estimation.ipynb
Normal file
466
assignment_05/spectral-estimation.ipynb
Normal file
@ -0,0 +1,466 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "0ff7abb1-c698-480b-a894-bdbb5d151fe6",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Assignment 5\n",
|
||||
"In this assignment, we look at spectral estimation and study the effects of acausal filters."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "156c8712-11be-4721-9d39-ff2c47a66bcb",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import numpy as np\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"from setupFigure import SetupFigure\n",
|
||||
"from dftFast import dft_fast_coeff, dft_fast_synthesis\n",
|
||||
"from seismicTrace import SeismicTrace"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "f98951f5-96dc-4ef5-b365-85bffa21f700",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Task 1: Functions for Hann window and filter transfer functions\n",
|
||||
"Write a function that calculates samples of a Hann window for given sampling interval and window length."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c36eb15e-26e7-4e6e-bef9-8d566dc07411",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hann_window(dt, tlen):\n",
|
||||
" \"\"\"\n",
|
||||
" Calculate samples of the Hann window for given DT and TLEN.\n",
|
||||
" Number of samples is assumed to be int(tlen/dt)\n",
|
||||
" :param dt: sampling interval\n",
|
||||
" :param tlen: length of window\n",
|
||||
" \"\"\"\n",
|
||||
" ns = int(tlen/dt)\n",
|
||||
" return 2*np.sin(np.pi*dt*np.arange(0, ns)/tlen)**2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "60dffc7b-17a1-40aa-8a6f-918504e06af2",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Write a function that calculates samples of the boxcar lowpass filter transfer function for positive frequencies only."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "be77830b-6b2f-4371-9711-e83a1598c363",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def boxcar_lowpass_filter(fc, df, nf):\n",
|
||||
" \"\"\"\n",
|
||||
" Calculates samples of the boxcar lowpass filter transfer function (positive frequencies only)\n",
|
||||
" :param fc: corner frequency in Hz\n",
|
||||
" :param df: frequency stepping\n",
|
||||
" :param nf: number of frequencies\n",
|
||||
" \"\"\"\n",
|
||||
" return np.where(df*np.arange(0, nf) > fc, 0, 1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "33eb7b1d-4abd-42a2-99ec-cdd1765fbfde",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Write a function that calculates samples of the boxcar highpass filter transfer function for positive frequencies only."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "29c56269-025a-43e9-8748-c0514a72f70d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def boxcar_highpass_filter(fc, df, nf):\n",
|
||||
" \"\"\"\n",
|
||||
" Calculates samples of the boxcar highpass filter transfer function (positive frequencies only)\n",
|
||||
" :param fc: corner frequency in Hz\n",
|
||||
" :param df: frequency stepping\n",
|
||||
" :param nf: number of frequencies\n",
|
||||
" \"\"\"\n",
|
||||
" return np.where(df*np.arange(0, nf) < fc, 0, 1)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "937b6b14-4d8f-40ed-bc71-86888d6e726c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Write a function that calculates samples of the Hann filter transfer function for positive frequencies only."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0101ff10-d14d-4b96-83f8-b26f96e5ec8d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def hann_lowpass_filter(fc, df, nf):\n",
|
||||
" \"\"\"\n",
|
||||
" Calculates samples of the Hann filter transfer function (positive frequencies only)\n",
|
||||
" :param fc: corner frequency in Hz\n",
|
||||
" :param df: frequency stepping\n",
|
||||
" :param nf: number of frequencies\n",
|
||||
" \"\"\"\n",
|
||||
" f = df*np.arange(0, nf)\n",
|
||||
" return np.where(f < fc, np.cos(np.pi*f/fc)**2, 0) "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d641182d-5526-45a9-a69a-0a6965fd942b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Task 2: Spectral estimation and windowing\n",
|
||||
"Here, we first setup a time series that consists of a superposition of different exponentially damped sine functions simulating a series of free oscillations:\n",
|
||||
"\\begin{align}\n",
|
||||
"s(t) = \\sum_{k=0}^N A_k\\sin(2\\pi f_k t)\\,\\exp(-\\pi f_k t/Q_k) \\,.\n",
|
||||
"\\end{align}\n",
|
||||
"The aim is to find the frequencies by Fourier analysis."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "eba91f73-1651-4fd7-ad90-70980b1c5d4d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"feig = np.array([0.3, 0.48, 0.64, 0.68, 0.82, 0.85, 0.93, 0.94])*1.e-3 # eigenfreqeuncies in Hz\n",
|
||||
"amp = np.array([1.0, 0.30, 2.00, 0.61, 4.00, 0.53, 3.00, 0.24]) # amplitudes\n",
|
||||
"phi = np.array([ 11, 46, 271, 123, 337, 173, 65, 221])*np.pi/180. # phases\n",
|
||||
"q = np.array([600, 200, 2000, 1000, 600, 100, 800, 900]) # quality factors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e455172a-50ad-4aa4-a1b3-d29d50a52b49",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Write code that impements the above equation using the provided frequencies, amplitudes, phases and Q values. Choose dt=100 s and allow a varaible time series length of tens of hours. Plot the resulting time series."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c808e6c4-8e39-4e7c-a689-860230ff775a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"nhour = 100\n",
|
||||
"dt = 100.0\n",
|
||||
"tlen = 3600*nhour\n",
|
||||
"ns = int(tlen/dt)\n",
|
||||
"print(\"Number of samples: \", ns)\n",
|
||||
"t = dt*np.arange(0, ns)\n",
|
||||
"seis = np.zeros(ns)\n",
|
||||
"for j, f in enumerate(feig):\n",
|
||||
" seis = seis + amp[j]*np.sin(2*np.pi*f*t+phi[j])*np.exp(-np.pi*f*t/q[j])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3d0dbe36-34e8-486d-bc63-f5be4aff2d0c",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig1, ax1 = SetupFigure(12, 5, \"Time [h|\", \"s(t)\", \"Ground motion\", 14)\n",
|
||||
"ax1.plot(t/3600, seis, color='blue', ls='-')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "7ae65e6e-0f73-42fc-b251-878f0ef7f36c",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Produce a second time series by multiplying the original one with a Hann window and also plot it."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b62c1a43-f57e-4397-a8f9-7ec813db1e9d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"win = hann_window(dt, tlen)\n",
|
||||
"seisw = seis*win"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "41193b3d-110b-42a4-b2ee-9ee0dbd759af",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig2, ax2 = SetupFigure(12, 5, \"Time [h|\", \"swin(t)\", \"Windowed ground motion\", 14)\n",
|
||||
"ax2.plot(t/3600, seisw, color='blue', ls='-')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "26feab1b-41a6-464f-b578-95814286b915",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Perform a fast Fourier analysis, calculate the associated frequencies and plot the resulting amplitude spectra of both the original and the windowed time series. Compare the results."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "164cd4c2-72ea-44e8-a236-95475118aad1",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"spec = dft_fast_coeff(seis)\n",
|
||||
"f = 1./tlen*np.arange(0, spec.size)\n",
|
||||
"print(\"Number of frequencies: \", spec.size, \" fmax = \", f[-1]*1000, \"mHz\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "0c88a619-8b9c-44ed-bc5f-f6ecce938af3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"specw = dft_fast_coeff(seisw)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "73b8fae2-e712-47d7-99a5-ebe5375084cf",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig3, ax3 = SetupFigure(12, 5, \"Frequency [mHz]\", \"S(f)\", \"Amplitude spectrum of ground motion\", 14)\n",
|
||||
"ax3.set_xlim(0,1.2)\n",
|
||||
"ax3.plot(f*1000, np.absolute(spec), color='blue', ls='-', label='boxcar')\n",
|
||||
"ax3.plot(f*1000, np.absolute(specw), color='red', ls='-', label='hann')\n",
|
||||
"ax3.legend()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "689b3af4-1146-4041-9f4e-baed098d2a23",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Task 2: Read a seismogram from file and compute spectrum\n",
|
||||
"Here, we first read a recorded seismogram form a file, do a Fourier analysis and later apply diverse acausal filters. We make use of the class \"SeismicTrace\" that defines a data structure for a seismic trace and also some useful functions related to traces. You may want to look at the provided code in \"seismicTrace.py\"."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "912ae1f7-8cbc-4446-9ef0-b446b57d789d",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"seisfile = \"CH.PANIX.HHZ\"\n",
|
||||
"with open(seisfile, 'r') as fd:\n",
|
||||
" seistrace = SeismicTrace.readFromAscii(fd)\n",
|
||||
"t = seistrace.tanf+seistrace.dt*np.arange(0, seistrace.nsamp)\n",
|
||||
"seistrace.printInfo()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "eaee9262-f577-49a1-acee-9b9c27f996be",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig4, ax4 = SetupFigure(12, 5, \"Time [s]\", \"s(t)\", \"Unfiltered seismic data\", 14)\n",
|
||||
"ax4.plot(t, seistrace.vals, color='blue', ls='-')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "934a4fa1-7f8d-4977-bf86-bfe094abc5e5",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Perform a fast Fourier analysis, calculate the associated frequencies and plot the resulting amplitude spectrum."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c4a0c8c9-b51a-4116-9988-73d75b2f6704",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"spec = dft_fast_coeff(seistrace.vals)\n",
|
||||
"f = 1./seistrace.tlen*np.arange(0, spec.size)\n",
|
||||
"print(\"Number of frequencies: \", spec.size, \" fmax = \", f[-1], \"Hz\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "82fb96d5-39ac-4c6a-a360-3544167ec26b",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig5, ax5 = SetupFigure(12, 5, \"Frequency [Hz]\", \"S(f)\", \"Amplitude spectrum of seismogram\", 14)\n",
|
||||
"ax5.set_xlim(0, 1)\n",
|
||||
"ax5.plot(f, np.absolute(spec), color='blue', ls='-', label='boxcar')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "8d36d0c3-6faf-4e0b-b934-8822100b2b2f",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Task 3: Acausal low pass filtering"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "36b37ff1-3080-4651-a344-9cb4ede9109d",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Apply the boxcar lowpass filter to the data and plot the result."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a1e59a76-d251-4d66-b6ba-7c29a0626b3e",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fc = 0.1\n",
|
||||
"df = 1./seistrace.tlen\n",
|
||||
"specfil = spec*boxcar_lowpass_filter(fc, df, spec.size)\n",
|
||||
"seisfil = dft_fast_synthesis(specfil)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "532ad374-2728-435d-8dca-afd7fcf9c475",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig6, ax6 = SetupFigure(12, 5, \"Time [s]\", \"sf(t)\", \"Boxcar lowpass filtered seismic data, FC = {:5.2f} Hz\".format(fc), 14)\n",
|
||||
"#ax6.set_xlim(64000, 64500)\n",
|
||||
"ax6.plot(t, seisfil, color='blue', ls='-')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "e1097e6d-c459-489d-aecd-75911419a319",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Apply the Hann low pass filter to the data and plot the result."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "be2e1d6d-0c4e-4bfa-8612-ce626393bdff",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"specfil2 = spec*hann_lowpass_filter(fc, df, spec.size)\n",
|
||||
"seisfil2 = dft_fast_synthesis(specfil2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "b5d4bf72-9bc2-4679-9178-4f7bc650e4ee",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig7, ax7 = SetupFigure(12, 5, \"Time [s]\", \"sf(t)\", \"Hann lowpass filtered seismic data, FC = {:5.2f}\".format(fc), 14)\n",
|
||||
"#ax7.set_xlim(64000, 64500)\n",
|
||||
"ax7.plot(t, seisfil2, color='blue', ls='-')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "3bbec473-2bf7-41d0-828d-9413dff147e8",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Apply the boxcar highpass filter to the data and plot the result."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "c9ec91f3-cc1c-48e5-ac53-882002fc74f6",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"specfil3 = spec*boxcar_highpass_filter(fc, df, spec.size)\n",
|
||||
"seisfil3 = dft_fast_synthesis(specfil3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7a24950e-8438-4e3b-903e-75f2f4408105",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fig8, ax8 = SetupFigure(12, 5, \"Time [s]\", \"sf(t)\", \"Boxcar highpass filtered seismic data, FC = {:5.2f}\".format(fc), 14)\n",
|
||||
"#ax7.set_xlim(64000, 64500)\n",
|
||||
"ax8.plot(t, seisfil3, color='blue', ls='-')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "92e0ebc5-9f7d-4302-8ad1-9aed6c7f2d6a",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"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.12.4"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user