{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Applying a Filter to a Time-Series\n\nThis example demonstrates low pass filtering a time-series by applying a\nweighted running mean over the time dimension.\n\nThe time-series used is the Darwin-only Southern Oscillation index (SOI),\nwhich is filtered using two different Lanczos filters, one to filter out\ntime-scales of less than two years and one to filter out time-scales of\nless than 7 years.\n\n## References\n\n    Duchon C. E. (1979) Lanczos Filtering in One and Two Dimensions.\n    Journal of Applied Meteorology, Vol 18, pp 1016-1022.\n\n    Trenberth K. E. (1984) Signal Versus Noise in the Southern Oscillation.\n    Monthly Weather Review, Vol 112, pp 326-332\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\nimport numpy as np\n\nimport iris\nimport iris.plot as iplt\n\n\ndef low_pass_weights(window, cutoff):\n    \"\"\"Calculate weights for a low pass Lanczos filter.\n\n    Args:\n\n    window: int\n        The length of the filter window.\n\n    cutoff: float\n        The cutoff frequency in inverse time steps.\n\n    \"\"\"\n    order = ((window - 1) // 2) + 1\n    nwts = 2 * order + 1\n    w = np.zeros([nwts])\n    n = nwts // 2\n    w[n] = 2 * cutoff\n    k = np.arange(1.0, n)\n    sigma = np.sin(np.pi * k / n) * n / (np.pi * k)\n    firstfactor = np.sin(2.0 * np.pi * cutoff * k) / (np.pi * k)\n    w[n - 1 : 0 : -1] = firstfactor * sigma\n    w[n + 1 : -1] = firstfactor * sigma\n    return w[1:-1]\n\n\ndef main():\n    # Load the monthly-valued Southern Oscillation Index (SOI) time-series.\n    fname = iris.sample_data_path(\"SOI_Darwin.nc\")\n    soi = iris.load_cube(fname)\n\n    # Window length for filters.\n    window = 121\n\n    # Construct 2-year (24-month) and 7-year (84-month) low pass filters\n    # for the SOI data which is monthly.\n    wgts24 = low_pass_weights(window, 1.0 / 24.0)\n    wgts84 = low_pass_weights(window, 1.0 / 84.0)\n\n    # Apply each filter using the rolling_window method used with the weights\n    # keyword argument. A weighted sum is required because the magnitude of\n    # the weights are just as important as their relative sizes.\n    soi24 = soi.rolling_window(\n        \"time\", iris.analysis.SUM, len(wgts24), weights=wgts24\n    )\n    soi84 = soi.rolling_window(\n        \"time\", iris.analysis.SUM, len(wgts84), weights=wgts84\n    )\n\n    # Plot the SOI time series and both filtered versions.\n    plt.figure(figsize=(9, 4))\n    iplt.plot(\n        soi,\n        color=\"0.7\",\n        linewidth=1.0,\n        linestyle=\"-\",\n        alpha=1.0,\n        label=\"no filter\",\n    )\n    iplt.plot(\n        soi24,\n        color=\"b\",\n        linewidth=2.0,\n        linestyle=\"-\",\n        alpha=0.7,\n        label=\"2-year filter\",\n    )\n    iplt.plot(\n        soi84,\n        color=\"r\",\n        linewidth=2.0,\n        linestyle=\"-\",\n        alpha=0.7,\n        label=\"7-year filter\",\n    )\n    plt.ylim([-4, 4])\n    plt.title(\"Southern Oscillation Index (Darwin Only)\")\n    plt.xlabel(\"Time\")\n    plt.ylabel(\"SOI\")\n    plt.legend(fontsize=10)\n    iplt.show()\n\n\nif __name__ == \"__main__\":\n    main()"
      ]
    }
  ],
  "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.10.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}