{
 "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",
    "#### 1.1 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",
    "    # Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "60dffc7b-17a1-40aa-8a6f-918504e06af2",
   "metadata": {},
   "source": [
    "#### 1.2 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",
    "    # Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33eb7b1d-4abd-42a2-99ec-cdd1765fbfde",
   "metadata": {},
   "source": [
    "#### 1.3 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",
    "    # Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "937b6b14-4d8f-40ed-bc71-86888d6e726c",
   "metadata": {},
   "source": [
    "#### 1.4 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",
    "    # Here comes your code"
   ]
  },
  {
   "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.14])               # 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": [
    "#### 2.1 Write code that implements 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": [
    "# Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ae65e6e-0f73-42fc-b251-878f0ef7f36c",
   "metadata": {},
   "source": [
    "#### 2.2 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": [
    "# Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "26feab1b-41a6-464f-b578-95814286b915",
   "metadata": {},
   "source": [
    "#### 2.3 Perform a fast Fourier analysis, calculate the associated frequencies and plot the resulting amplitude spectra of both the original and the windowed time series into one graph. Compare the results. Try different time series lengths (between 20 and 200 hours)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "164cd4c2-72ea-44e8-a236-95475118aad1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "689b3af4-1146-4041-9f4e-baed098d2a23",
   "metadata": {},
   "source": [
    "### Task 3: 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": [
    "#### 3.1 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 4: 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": [
    "# Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1097e6d-c459-489d-aecd-75911419a319",
   "metadata": {},
   "source": [
    "#### 4.1 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": [
    "# Here comes your code"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3bbec473-2bf7-41d0-828d-9413dff147e8",
   "metadata": {},
   "source": [
    "#### 4.2 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": [
    "# Here comes your code"
   ]
  }
 ],
 "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
}
