{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "\n", "import datetime\n", "\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "\n", "import pandas as pd\n", "\n", "import utide\n", "\n", "print(utide.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Look at the data file to see what structure it has." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open(\"can1998.dtf\") as f:\n", " lines = f.readlines()\n", "\n", "print(\"\".join(lines[:5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It looks like the fields are seconds, year, month, day, hour, elevation, flag. We need a date parser function to combine the date and time fields into a single value to be used as the datetime index." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": false }, "outputs": [], "source": [ "names = [\"seconds\", \"year\", \"month\", \"day\", \"hour\", \"elev\", \"flag\"]\n", "\n", "obs = pd.read_csv(\n", " \"can1998.dtf\",\n", " names=names,\n", " skipinitialspace=True,\n", " delim_whitespace=True,\n", " na_values=\"9.990\",\n", ")\n", "\n", "\n", "date_cols = [\"year\", \"month\", \"day\", \"hour\"]\n", "index = pd.to_datetime(obs[date_cols])\n", "obs = obs.drop(date_cols, axis=1)\n", "obs.index = index\n", "\n", "obs.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Although there are no elevations marked bad via special value, which should be `nan` after reading the file, the flag value of 2 indicates the values are unreliable, so we will mark them with `nan`, calculate the deviations of the elevations from their mean (stored in a new column called \"anomaly\"), and then interpolate to fill in the `nan` values in the anomaly." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bad = obs[\"flag\"] == 2\n", "corrected = obs[\"flag\"] == 1\n", "\n", "obs.loc[bad, \"elev\"] = np.nan\n", "obs[\"anomaly\"] = obs[\"elev\"] - obs[\"elev\"].mean()\n", "obs[\"anomaly\"] = obs[\"anomaly\"].interpolate()\n", "print(f\"{bad.sum()} points were flagged 'bad' and interpolated\")\n", "print(f\"{corrected.sum()} points were flagged 'corrected' and left unchanged\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we can call solve to obtain the coefficients." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "coef = utide.solve(\n", " obs.index,\n", " obs[\"anomaly\"],\n", " lat=-25,\n", " method=\"ols\",\n", " conf_int=\"MC\",\n", " verbose=False,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The amplitudes and phases from the fit are now in the `coef` data structure (a Bunch), which can be used directly in the `reconstruct` function to generate a hindcast or forecast of the tides at the times specified in the `time` array." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(coef.keys())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tide = utide.reconstruct(obs.index, coef, verbose=False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The output from the reconstruction is also a Bunch:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(tide.keys())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t = obs.index.to_pydatetime()\n", "\n", "fig, (ax0, ax1, ax2) = plt.subplots(figsize=(17, 5), nrows=3, sharey=True, sharex=True)\n", "\n", "ax0.plot(t, obs.anomaly, label=\"Observations\", color=\"C0\")\n", "ax1.plot(t, tide.h, label=\"Prediction\", color=\"C1\")\n", "ax2.plot(t, obs.anomaly - tide.h, label=\"Residual\", color=\"C2\")\n", "fig.legend(ncol=3, loc=\"upper center\");" ] } ], "metadata": { "anaconda-cloud": {}, "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.10.4" } }, "nbformat": 4, "nbformat_minor": 1 }