Skip to content

Commit

Permalink
Mia week4 (FlorisCalkoen#89)
Browse files Browse the repository at this point in the history
* updated for 4b

* final 4b

* formatting

---------

Co-authored-by: floriscalkoen <[email protected]>
  • Loading branch information
pupicvuriljm and floriscalkoen authored Mar 7, 2024
1 parent 1fcdab0 commit 5abc9d4
Show file tree
Hide file tree
Showing 2 changed files with 577 additions and 4 deletions.
317 changes: 317 additions & 0 deletions notebooks/4b_shallow_water_tides.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,317 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "070a3d1e-3e53-4d9d-adf0-1100343150ea",
"metadata": {},
"source": [
"# Shallow Water Tides\n",
"\n",
"Building upon our previous analysis of tidal characters and main tidal constituents, this notebook delves into Chapter 5 of the textbook, where you gained insights into tidal propagation in coastal waters and higher harmonic tidal constituents. Here, our primary focus will be on ***shallow-water tides***, also known as ***overtides***, explained in chapter 5.7.5 of the textbook.\n",
"Shallow-water tides are generated as a result of non-linear effects in shallow coastal waters and tidal basins. Unlike the basic astronomical constituents driven by tidal forces from the Earth, Moon, and Sun, shallow-water tides have periods that are integer fractions (1/2, 1/3, etc.) of these basic periods. This characteristic gives them the name overtides. We will not repeat the whole theory here, so make sure you followed these weeks lectures and Chapter 5 of the textbook. Some of the overtides are:\n",
"- M2 higher harmonics: M3, M4, M6, M8\n",
"- S2 higher harmonics: S4, S6, S8\n",
"- Tides generated by interaction of different tidal components: MS4, MN4\n",
"\n",
"\n",
"In this notebook, we will explore overtides using python code and introduce a new method of obtaining the tidal signal and making tidal predictions. Therefore, please import the libraries that we need for the analysis from the cell below.\n"
]
},
{
"cell_type": "markdown",
"id": "68b6986c-fd53-474d-ad6e-4e371c9bac63",
"metadata": {},
"source": [
"## Add additional package\n",
"\n",
"This week we have added a new package to the environment. So to run this notebook you will have to install this. You can do this by activating your environment, and then installing the package. The package that we want to install is utide. Because it's a pure Python package, that is not available on the conda channels, we will install it with pip. \n",
"\n",
"The commands that you have to run in a miniforge prompt: \n",
"```bash\n",
"mamba activate coastal\n",
"pip install coastal\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9b2ce2ff-523a-4801-9dce-e70af8c20a05",
"metadata": {},
"outputs": [],
"source": [
"import pathlib\n",
"from pathlib import Path\n",
"import sys\n",
"import warnings\n",
"import ipywidgets as widgets\n",
"from ipywidgets import interact\n",
"from matplotlib.patches import Patch\n",
"from matplotlib.ticker import MaxNLocator, StrMethodFormatter\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.dates as mdates\n",
"import numpy as np\n",
"import pandas as pd\n",
"import cartopy.crs as ccrs\n",
"import xarray as xr\n",
"from datetime import datetime, timedelta\n",
"from IPython.display import display, Image\n",
"import math\n",
"import pandas as pd\n",
"import pooch\n",
"import pickle\n",
"from scipy import stats\n",
"with warnings.catch_warnings():\n",
" warnings.simplefilter(\"ignore\", category=RuntimeWarning)\n",
" import utide\n",
"\n",
"cwd = pathlib.Path().resolve()\n",
"proj_dir = cwd.parent.parent.parent # this is the root of the CoastalCodeBook\n",
"sys.path.append(str(proj_dir))\n",
"\n",
"from initialize.Tide_Initialize import plot_2timeseries_with_interactive_controls, questions_4b"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "30da269b-6d4f-4bcc-87ac-9ae5ed3050d2",
"metadata": {},
"source": [
"<br><br>\n",
"## 1. Visualisation of shallow-water tides\n",
"\n",
"Now that we are familiar with shallow-water tides, we can visualise them. To do this, we will plot the tidal signals at Scheveningen and Jakarta, using the same methodology as in the previous notebooks.\n",
"\n",
"Execute the block below to generate an interactive figure. The figure displays the individual tidal components (upper plot), their combined tidal signal (second plot), and the total tidal signal (third plot) for the two locations.\n",
"\n",
"You can adjust the plotted time range using the slider (from 1 to 15 days) and select which tidal constituents to display with tick boxes. This allows you to experiment with different constituents, observe the resulting signals, and compare the locations.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4895150e-a8ea-428f-adca-38a998cb2f6d",
"metadata": {},
"outputs": [],
"source": [
"# Choose tidal constituents\n",
"comps = ['M2', 'S2', 'N2', 'K2', #semi-diurnal\n",
" 'K1', 'O1', 'P1', 'Q1', #diurnal\n",
" 'M3', 'M4', 'M6', 'M8', 'S4', 'MN4', 'MS4'] #short period (overtides)\n",
"\n",
"# We choose 15 days to plot\n",
"dates = np.array([\n",
" datetime(2000, 1, 1, 0, 0, 0) + timedelta(seconds=item * 3600)\n",
" for item in range(24*15) #15 days\n",
"])\n",
"\n",
"# download and load tidal signals\n",
"scheveningen_fp = pooch.retrieve(\n",
" \"https://coclico.blob.core.windows.net/coastal-dynamics/2_wind_waves_tides/tide_scheveningen.p\",\n",
" known_hash=\"4ebac210fc0893e52655cbc3c9501a6c805e3537f327fed7edb9e7dbfe7fa06a\",\n",
")\n",
"jakarta_fp = pooch.retrieve(\n",
" \"https://coclico.blob.core.windows.net/coastal-dynamics/2_wind_waves_tides/tide_jakarta.p\",\n",
" known_hash=\"7950246c47e757d9dd427063d7c809fda4267ed119efd18de43237aa9f98c9c6\",\n",
")\n",
"with open(scheveningen_fp, 'rb') as pickle_file:\n",
" scheveningen = pickle.load(pickle_file)\n",
"with open(jakarta_fp, 'rb') as pickle_file:\n",
" jakarta = pickle.load(pickle_file)\n",
"\n",
"tide = {\n",
" 'Scheveningen': scheveningen,\n",
" 'Jakarta': jakarta,\n",
" }\n",
"\n",
"plot_2timeseries_with_interactive_controls(comps, dates, tide)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f4d487a8-8819-448d-9799-1979159a7a56",
"metadata": {},
"outputs": [],
"source": [
"# Run this cell to get questions\n",
"questions_4b()"
]
},
{
"cell_type": "markdown",
"id": "b75bb66c-6ac4-4c28-96ad-9fe0d42483af",
"metadata": {},
"source": [
"<br><br>\n",
"## 2. Tidal Reconstruction & Prediction\n",
"\n",
"Because the tide is caused by regular astronomical phenomena, it can be predicted accurately a long time ahead (although not including meteorological effects such as storm surges). While we've utilized global model data from FES2014 in our previous analyses, it's important to note that the tidal signal at a particular location can also be derived from measured sea levels through harmonic analysis.\n",
"\n",
"In this part of the notebook, we will analyse the tidal signal obtained from the measured sea level. \n",
"For this, we will use the [utide](https://github.com/wesleybowman/UTide/tree/master) Python package, which is a Python adaptation of the Matlab [UTide](https://nl.mathworks.com/matlabcentral/fileexchange/46523-utide-unified-tidal-analysis-and-prediction-functions) package. It is a unified tidal analysis framework used for carrying out tidal analysis on a multi-year sequence of observations collected at irregularly spaced times. We will again use the [GESLA-3 (Global Extreme Sea Level Analysis)](https://gesla787883612.wordpress.com/) sea level records at Scheveningen.\n",
"\n",
"\n",
"### Reconstruction\n",
"\n",
"Here we will briefly show how to reconstruct the tidal signal from a measured timeseries. Take a look at the cell below where we do reconstruction and then run it.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "036fa1bf-515b-4f50-b286-ebea13a82f6f",
"metadata": {},
"outputs": [],
"source": [
"tide_gauge_fp = pooch.retrieve(\n",
" \"https://coclico.blob.core.windows.net/coastal-dynamics/2_wind_waves_tides/Scheveningen_GESLA.pkl\",\n",
" known_hash=\"90355584803ddcdf88b01fcf02546c4d8201a3fa6f63355ecfdb8ab6a07d1e38\",\n",
")\n",
"tide_gauge = pd.read_pickle(tide_gauge_fp)\n",
"\n",
"\n",
"tide_gauge.dropna(inplace=True)\n",
"time = tide_gauge.index\n",
" \n",
"# Linear regression\n",
"t_numeric = np.arange(len(time))\n",
"slope, intercept, r_value, p_value, std_err = stats.linregress(t_numeric, tide_gauge)\n",
" \n",
"# Detrend the series\n",
"detrended_series = tide_gauge - (slope * t_numeric + intercept)\n",
" \n",
"# Solve for tidal coefficients\n",
"coef = utide.solve(\n",
" time, detrended_series,\n",
" lat=52.099, # latitude of Scheveningen in GESLA\n",
" method='ols',\n",
" nodal=True,\n",
" trend=False,\n",
" conf_int='MC',\n",
")\n",
" \n",
"# Reconstruct tidal signal\n",
"result = utide.reconstruct(time, coef)\n",
"tide = pd.Series(result.h, index=result.t_in)\n",
"\n",
"## This could take several minutes, depending on your computer, so please wait a bit. You will get the following:\n",
"# solve: matrix prep ... solution ... done.\n",
"# prep/calcs ... done.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c0d86602-b939-474b-87a9-c0b109b3013e",
"metadata": {},
"outputs": [],
"source": [
"## Plot\n",
"# Choose a time window to plot (has to be between 1977 - 2017)\n",
"start_date = \"2015-05-01 00:00\"\n",
"end_date = \"2015-05-20 00:00\"\n",
"\n",
"filtered_tide = tide[start_date:end_date]\n",
"filtered_gauge = tide_gauge[start_date:end_date]\n",
"var = [filtered_gauge, filtered_tide, filtered_gauge-filtered_tide]\n",
"label = ['Measured sea level', 'Reconstructed tide', 'Non-tidal residual']\n",
"color = ['black', 'blue', 'orange']\n",
"fig, ax = plt.subplots(figsize=(12, 6), sharex=True)\n",
"for i in range(len(var)):\n",
" ax.plot(var[i], label=label[i], color=color[i])\n",
" ax.set_ylim(-1.5,2)\n",
" ax.set_yticks([-1, 0, 1])\n",
"\n",
"ax.set_title('Scheveningen', fontsize=12, fontweight='bold')\n",
"ax.set_ylabel('Sea Level [m]', ha='center', va='center', rotation='vertical', fontsize=12)\n",
"ax.legend(loc='upper right')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "e7f56916-073c-4f70-8e68-ce858c895bfb",
"metadata": {},
"source": [
"<br>\n",
"Remember the similar plot from 2d_tidal_constituents. There we asked you if you can try to explain why the tidal signal doesn't perfectly match the observed sea level. This time we could also calculate the non-tidal residual. The non-tidal residual is the part of the sea level that remains once the astronomical tidal component has been removed. This primarily contains the meteorological contribution to sea level, often called the surge. However, it may also contain some non-linear interactions."
]
},
{
"cell_type": "markdown",
"id": "56dcea69-b1e9-4d9a-bde0-ef1115176c7d",
"metadata": {},
"source": [
"\n",
"<br><br>\n",
"### Prediction\n",
"\n",
"Utide can also be used for future simulation of tidal signals. Take a look at the code below and run the cell."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5f7eb0d4-ea81-4a75-bd83-f0a3aabe8b0a",
"metadata": {},
"outputs": [],
"source": [
"# Simulation dates (feel free to choose your own)\n",
"start_date = '2015-01-01'\n",
"end_date = '2040-12-31'\n",
"\n",
"d_pred = pd.date_range(start=start_date, end=end_date, freq='h')\n",
"\n",
"# Predict tidal signal\n",
"sim = utide.reconstruct(d_pred, coef)\n",
"tide_sim = pd.Series(sim.h, index=sim.t_in)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2d3b4d8d-c180-4fe7-9492-ccb3c9a30ed1",
"metadata": {},
"outputs": [],
"source": [
"## Plot\n",
"# Choose a time window to plot (has to be in the interval you choose for prediction)\n",
"start_date = \"2025-05-01 00:00\"\n",
"end_date = \"2030-05-20 00:00\"\n",
"\n",
"filtered_tide_sim = tide_sim[start_date:end_date]\n",
"\n",
"plt.subplots(figsize=(10, 6))\n",
"plt.plot(filtered_tide_sim)\n",
"plt.title('Prediction of the tidal signal at Scheveningen')\n",
"plt.xlabel('Time')\n",
"plt.ylabel('Tidal signal [m]')\n",
"plt.show()\n",
"print('\\n Now we have the tidal signal for dates in which the observations are not yet available.')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:coastal]",
"language": "python",
"name": "conda-env-coastal-py"
},
"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.11.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit 5abc9d4

Please sign in to comment.