{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "c5711338-01f0-4e88-996d-b6026eff5098",
   "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": "code",
   "execution_count": 2,
   "id": "88aba420-be35-4070-8b6d-386fd924d0e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "def lowpass_first_order(fc, df, nf, napp):\n",
    "    \"\"\"\n",
    "    Calculates samples of the lowpass first order causal 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",
    "    :param napp: number of applications of filter\n",
    "    \"\"\"\n",
    "    f = df*np.arange(0, nf)\n",
    "    return (1j/(f/fc-1j))**napp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "89fda9ef-eca1-484f-9ba2-8ac9046c85f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def lowpass_second_order(fc, df, nf, phi):\n",
    "    \"\"\"\n",
    "    Calculates samples of the lowpass second order causal 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",
    "    :param phi: filter angle in degrees\n",
    "    \"\"\"\n",
    "    f = df*np.arange(0, nf)\n",
    "    alfa = np.deg2rad(phi)\n",
    "    return (-1j)/(f/fc-np.exp(1j*alfa))*(-1j)/(f/fc-np.exp(1j*(np.pi-alfa)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "d21fcbb1-52a3-4fca-8fc8-921034122836",
   "metadata": {},
   "outputs": [],
   "source": [
    "def butterworth_lowpass(fc, df, nf, order):\n",
    "    \"\"\"\n",
    "    Calculates samples of the lowpass Butterworth 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",
    "    :param order: filter order\n",
    "    \"\"\"\n",
    "    f = df*np.arange(0, nf)\n",
    "    h = np.ones(nf, dtype=np.complex64)\n",
    "    for k in range(order):\n",
    "        arg = 1j*(2*k+1)*np.pi/(2*order)\n",
    "        h = h*(-1j)/(f/fc-np.exp(arg))\n",
    "    return h"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c9938cab-7ae5-48ed-93d5-83215a350c18",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Identification:  CH.PANIX HHZ\n",
      "Sampling interval:  0.0500000007\n",
      "Number of samples:  47598\n",
      "Start time after midnight:  63621.435001\n",
      "Length of trace: (N*DT)  2379.9000333186\n"
     ]
    }
   ],
   "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": 6,
   "id": "57f8f053-fb38-4033-ae49-e70028095274",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x112a4a360>]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 101704 characters]",
      "text/plain": [
       "<Figure size 1200x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig1, ax1 = SetupFigure(12, 5, \"Time [s]\", \"s(t)\", \"Unfiltered seismic data\", 14)\n",
    "ax1.set_xlim(64200, 64400)\n",
    "ax1.plot(t, seistrace.vals, color='blue', ls='-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "56eb0313-e1a2-404e-9bc1-0ded3791f345",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of frequencies:  23800  fmax =  9.999999860000003 Hz\n"
     ]
    }
   ],
   "source": [
    "spec = dft_fast_coeff(seistrace.vals)\n",
    "df = 1./seistrace.tlen\n",
    "f = df*np.arange(0, spec.size)\n",
    "print(\"Number of frequencies: \", spec.size, \" fmax = \", f[-1], \"Hz\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "afc7c27a-173d-4339-b4ac-abfbd6b5e974",
   "metadata": {},
   "outputs": [],
   "source": [
    "fc = 0.1\n",
    "specfil1 = spec*lowpass_first_order(fc, df, spec.size, 1)\n",
    "seisfil1 = dft_fast_synthesis(specfil1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "efb6e3c6-2a82-45a2-8c17-336614d36b1b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 66468 characters]",
      "text/plain": [
       "<Figure size 1200x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig2, ax2 = SetupFigure(12, 3, \"Time [s]\", \"sf(t)\", \n",
    "                        \"Lowpass first order filtered seismic data, FC = {:5.2f} Hz, NAPP = {:d}\".format(fc, 1), 14)\n",
    "ax2.set_xlim(64200, 64400)\n",
    "ldum = ax2.plot(t, seisfil1, color='blue', ls='-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "50e6cc4c-4c9c-47a5-ba4f-04808b64db31",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58844 characters]",
      "text/plain": [
       "<Figure size 1200x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fc = 0.1\n",
    "specfil2 = spec*lowpass_first_order(fc, df, spec.size, 2)\n",
    "seisfil2 = dft_fast_synthesis(specfil2)\n",
    "fig3, ax3 = SetupFigure(12, 3, \"Time [s]\", \"sf(t)\", \n",
    "                        \"Lowpass first order filtered seismic data, FC = {:5.2f} Hz, NAPP = {:d}\".format(fc,2), 14)\n",
    "ax3.set_xlim(64200, 64400)\n",
    "ldum = ax3.plot(t, seisfil2, color='blue', ls='-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a54f6ee3-480e-4178-b4d6-04a01d47a3c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 54192 characters]",
      "text/plain": [
       "<Figure size 1200x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fc = 0.1\n",
    "specfil3 = spec*lowpass_first_order(fc, df, spec.size, 3)\n",
    "seisfil3 = dft_fast_synthesis(specfil3)\n",
    "fig4, ax4 = SetupFigure(12, 3, \"Time [s]\", \"sf(t)\", \n",
    "                        \"Lowpass first order filtered seismic data, FC = {:5.2f} Hz, NAPP = {:d}\".format(fc,3), 14)\n",
    "ax4.set_xlim(64200, 64400)\n",
    "ldum = ax4.plot(t, seisfil3, color='blue', ls='-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "45fd47e8-0400-4c3d-bb2a-1ba15bb27c84",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 61412 characters]",
      "text/plain": [
       "<Figure size 1200x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fc = 0.1\n",
    "specfil4 = spec*lowpass_second_order(fc, df, spec.size, 5)\n",
    "seisfil4 = dft_fast_synthesis(specfil4)\n",
    "fig5, ax5 = SetupFigure(12, 3, \"Time [s]\", \"sf(t)\", \n",
    "                        \"Lowpass 2nd order filtered seismic data, FC = {:5.2f} Hz, PHI = {:3.0f}\".format(fc, 5), 14)\n",
    "ax5.set_xlim(64200, 64400)\n",
    "ldum = ax5.plot(t, seisfil4, color='blue', ls='-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "0b292eda-a26d-443c-8c58-b16011d63403",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58700 characters]",
      "text/plain": [
       "<Figure size 1200x300 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fc = 0.1\n",
    "specfil5 = spec*lowpass_second_order(fc, df, spec.size, 45)\n",
    "seisfil5 = dft_fast_synthesis(specfil5)\n",
    "fig6, ax6 = SetupFigure(12, 3, \"Time [s]\", \"sf(t)\", \n",
    "                        \"Lowpass 2nd order filtered seismic data, FC = {:5.2f} Hz, PHI = {:3.0f}\".format(fc, 45), 14)\n",
    "ax6.set_xlim(64200, 64400)\n",
    "ldum = ax6.plot(t, seisfil5, color='blue', ls='-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0de14535-8b80-4921-95b2-e4cb917f9bac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 114120 characters]",
      "text/plain": [
       "<Figure size 1200x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig7, ax7 = SetupFigure(12, 5, \"Time [s]\", \"sf(t)\", \"Butterworth lowpass filtered seismic data, FC = {:5.2f} Hz\".format(fc), 14)\n",
    "ax7.set_xlim(64200, 64400)\n",
    "fc = 0.1\n",
    "for order in range(1,9):\n",
    "    specfil = spec*butterworth_lowpass(fc, df, spec.size, order)\n",
    "    seisfil = dft_fast_synthesis(specfil)\n",
    "    snorm = abs(max(seisfil))\n",
    "    ldum = ax7.plot(t, seisfil/snorm+order, color='blue', ls='-', lw=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c0a5c2c0-827c-4205-a70a-73e9b1fa6872",
   "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
}
