From ccf2755b28489b3beb3a84a791100e5f87c65ca7 Mon Sep 17 00:00:00 2001 From: tsutterley Date: Wed, 6 Nov 2024 15:33:28 -0800 Subject: [PATCH 1/3] fix: allow variable case for Doodson number formalisms feat: added property for Extended Doodson numbers fix: use Love numbers for long-period tides when inferring (won't affect tilt factors) --- pyTMD/arguments.py | 15 ++++++++------- pyTMD/io/constituents.py | 24 +++++++++++++++++++++--- pyTMD/io/model.py | 12 +++++++----- pyTMD/predict.py | 14 ++++++++++---- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/pyTMD/arguments.py b/pyTMD/arguments.py index 52843f21..93c3d5cf 100755 --- a/pyTMD/arguments.py +++ b/pyTMD/arguments.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" arguments.py -Written by Tyler Sutterley (10/2024) +Written by Tyler Sutterley (11/2024) Calculates the nodal corrections for tidal constituents Modification of ARGUMENTS fortran subroutine by Richard Ray 03/1999 @@ -38,6 +38,7 @@ Ocean Tides", Journal of Atmospheric and Oceanic Technology, (2002). UPDATE HISTORY: + Updated 11/2024: allow variable case for Doodson number formalisms Updated 10/2024: can convert Doodson numbers formatted as strings update Doodson number conversions to follow Cartwright X=10 convention add function to parse Cartwright/Tayler/Edden tables @@ -478,13 +479,13 @@ def doodson_number( else: return None # extract identifier in formalism - if (kwargs['formalism'] == 'Cartwright'): + if (kwargs['formalism'].title() == 'Cartwright'): # extract Cartwright number numbers = np.array(coefficients[:6,0]) - elif (kwargs['formalism'] == 'Doodson'): + elif (kwargs['formalism'].title() == 'Doodson'): # convert from coefficients to Doodson number numbers = _to_doodson_number(coefficients[:,0], **kwargs) - elif (kwargs['formalism'] == 'Extended'): + elif (kwargs['formalism'].title() == 'Extended'): # convert to extended Doodson number in UKHO format numbers = _to_extended_doodson(coefficients[:,0], **kwargs) else: @@ -502,13 +503,13 @@ def doodson_number( numbers[c] = None continue # convert from coefficients to Doodson number - if (kwargs['formalism'] == 'Cartwright'): + if (kwargs['formalism'].title() == 'Cartwright'): # extract Cartwright number numbers[c] = np.array(coefficients[:6,0]) - elif (kwargs['formalism'] == 'Doodson'): + elif (kwargs['formalism'].title() == 'Doodson'): # convert from coefficients to Doodson number numbers[c] = _to_doodson_number(coefficients[:,0], **kwargs) - elif (kwargs['formalism'] == 'Extended'): + elif (kwargs['formalism'].title() == 'Extended'): # convert to extended Doodson number in UKHO format numbers[c] = _to_extended_doodson(coefficients[:,0], **kwargs) # return the Doodson or Cartwright number diff --git a/pyTMD/io/constituents.py b/pyTMD/io/constituents.py index 6102ce7b..517269c8 100644 --- a/pyTMD/io/constituents.py +++ b/pyTMD/io/constituents.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" constituents.py -Written by Tyler Sutterley (10/2024) +Written by Tyler Sutterley (11/2024) Basic tide model constituent class PYTHON DEPENDENCIES: @@ -10,6 +10,7 @@ https://numpy.org/doc/stable/user/numpy-for-matlab-users.html UPDATE HISTORY: + Updated 11/2024: added property for Extended Doodson numbers Updated 10/2024: added property for the shape of constituent fields Updated 09/2024: add more known constituents to string parser function Updated 08/2024: add GOT prime nomenclature for 3rd degree constituents @@ -166,7 +167,7 @@ def phase(self, field: str): @property def doodson_number(self): - """constituent Doodson number + """Doodson number for constituents """ doodson_numbers = [] # for each constituent ID @@ -183,7 +184,7 @@ def doodson_number(self): @property def cartwright_number(self): - """constituent Cartwright numbers + """Cartwright numbers for constituents """ cartwright_numbers = [] # for each constituent ID @@ -198,6 +199,23 @@ def cartwright_number(self): # return the list of Cartwright numbers return cartwright_numbers + @property + def extended_doodson(self): + """Extended Doodson numbers for constituents + """ + extended_numbers = [] + # for each constituent ID + for f in self.fields: + try: + # try to get the Extended Doodson number + XDO = pyTMD.arguments.doodson_number(f, formalism='Extended') + except (AssertionError, ValueError) as exc: + XDO = None + # add Extended Doodson number to the combined list + extended_numbers.append(XDO) + # return the list of Extended Doodson numbers + return extended_numbers + @property def shape(self): """Shape of constituent fields diff --git a/pyTMD/io/model.py b/pyTMD/io/model.py index 14cdcd9e..dace713b 100644 --- a/pyTMD/io/model.py +++ b/pyTMD/io/model.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" model.py -Written by Tyler Sutterley (10/2024) +Written by Tyler Sutterley (11/2024) Retrieves tide model parameters for named tide models and from model definition files @@ -11,6 +11,7 @@ https://numpy.org/doc/stable/user/numpy-for-matlab-users.html UPDATE HISTORY: + Updated 11/2024: use Love numbers for long-period tides in node equilibrium Updated 10/2024: add wrapper functions to read and interpolate constants add functions to append node tide equilibrium values to amplitudes remove redundant default keyword arguments to readers and interpolators @@ -421,7 +422,7 @@ def long_name(self) -> str: elif (self.type == 'z') and (self.variable == 'tide_load'): return 'load_tide_elevation' elif (self.type == 'z') and (self.variable == 'tide_lpe'): - return 'Equilibrium_Tide' + return 'equilibrium_tide_elevation' elif (self.type == ['u','v']): return dict(u='zonal_tidal_current', v='meridional_tidal_current') else: @@ -1203,9 +1204,10 @@ def node_equilibrium(lat: np.ndarray): """ # Cartwright and Edden potential amplitude amajor = 0.027929# node - # love numbers - k2 = 0.302 - h2 = 0.609 + # Love numbers for long-period tides (Wahr, 1981) + k2 = 0.299 + h2 = 0.606 + # tilt factor: response with respect to the solid earth gamma_2 = (1.0 + k2 - h2) # 2nd degree Legendre polynomials P20 = 0.5*(3.0*np.sin(lat*np.pi/180.0)**2 - 1.0) diff --git a/pyTMD/predict.py b/pyTMD/predict.py index 14212edd..abde477b 100644 --- a/pyTMD/predict.py +++ b/pyTMD/predict.py @@ -1,7 +1,7 @@ #!/usr/bin/env python u""" predict.py -Written by Tyler Sutterley (10/2024) +Written by Tyler Sutterley (11/2024) Prediction routines for ocean, load, equilibrium and solid earth tides REFERENCES: @@ -20,6 +20,7 @@ spatial.py: utilities for working with geospatial data UPDATE HISTORY: + Updated 11/2024: use Love numbers for long-period tides when inferring Updated 10/2024: use PREM as the default Earth model for Love numbers more descriptive error message if cannot infer minor constituents updated calculation of long-period equilibrium tides @@ -771,6 +772,7 @@ def _infer_diurnal( j1, = j # Love numbers of degree 2 for constituent h2, k2, l2 = _body_tide_love_numbers(omajor[i]) + # tilt factor: response with respect to the solid earth gamma_2 = (1.0 + k2 - h2) # "normalize" tide values z[:,i] = zmajor[:,j1]/(amajor[i]*gamma_2) @@ -833,6 +835,7 @@ def _infer_diurnal( for k in minor_indices: # Love numbers of degree 2 for constituent h2, k2, l2 = _body_tide_love_numbers(omega[k]) + # tilt factor: response with respect to the solid earth gamma_2 = (1.0 + k2 - h2) # interpolate from major constituents if (kwargs['method'].lower() == 'linear'): @@ -1228,12 +1231,15 @@ def equilibrium_tide( G = np.dot(fargs, coef) Z = np.inner(np.cos(G*np.pi/180.0), CTE) - # Multiply by gamma_2 * normalization * P20(lat) - k2 = 0.302 - h2 = 0.609 + # Love numbers for long-period tides (Wahr, 1981) + k2 = 0.299 + h2 = 0.606 + # tilt factor: response with respect to the solid earth gamma_2 = (1.0 + k2 - h2) + # 2nd degree Legendre polynomials P20 = 0.5*(3.0*np.sin(lat*np.pi/180.0)**2 - 1.0) # calculate long-period equilibrium tide and convert to meters + # Multiply by gamma_2 * normalization * P20(lat) if (nlat != nt): lpet = gamma_2*np.sqrt((4.0+1.0)/(4.0*np.pi))*np.outer(P20,Z/100.0) else: From fae2e7eb74d758d23995ec4b5c087b24dc2a13b0 Mon Sep 17 00:00:00 2001 From: tsutterley Date: Thu, 7 Nov 2024 12:02:58 -0800 Subject: [PATCH 2/3] docs: add form factor notebook --- doc/source/_assets/tide_form_factor.png | Bin 0 -> 75244 bytes .../notebooks/Plot-Tide-Form-Factor.ipynb | 285 ++++++++++++++++++ doc/source/user_guide/Examples.rst | 6 + 3 files changed, 291 insertions(+) create mode 100644 doc/source/_assets/tide_form_factor.png create mode 100644 doc/source/notebooks/Plot-Tide-Form-Factor.ipynb diff --git a/doc/source/_assets/tide_form_factor.png b/doc/source/_assets/tide_form_factor.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa18a5e8b937e168e569f3782f58dc29228be9a GIT binary patch literal 75244 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%0Dv3^R#xMZ-f|>N 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 literal 0 HcmV?d00001 diff --git a/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb b/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb new file mode 100644 index 00000000..8aadc759 --- /dev/null +++ b/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb @@ -0,0 +1,285 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot Tide Form Factor\n", + "======================\n", + "\n", + "This ({nb-download}`notebook `) demonstrates plotting daily tidal form factors for determining the dominant species of a region using the classifications from [Courtier (1938)](https://journals.lib.unb.ca/index.php/ihr/article/download/27428/1882520184). The dominant species classifications do have limitations as pointed out by [Amin (1986)](https://journals.lib.unb.ca/index.php/ihr/article/download/23443/27218/0).\n", + "\n", + "OTIS format tidal solutions provided by Oregon State University and ESR \n", + "- [http://volkov.oce.orst.edu/tides/region.html](http://volkov.oce.orst.edu/tides/region.html) \n", + "- [https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/](https://www.esr.org/research/polar-tide-models/list-of-polar-tide-models/)\n", + "- [ftp://ftp.esr.org/pub/datasets/tmd/](ftp://ftp.esr.org/pub/datasets/tmd/) \n", + "\n", + "Global Tide Model (GOT) solutions provided by Richard Ray at GSFC \n", + "- [https://earth.gsfc.nasa.gov/geo/data/ocean-tide-models](https://earth.gsfc.nasa.gov/geo/data/ocean-tide-models)\n", + "\n", + "Finite Element Solution (FES) provided by AVISO \n", + "- [https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html](https://www.aviso.altimetry.fr/en/data/products/auxiliary-products/global-tide-fes.html)\n", + " \n", + "## Python Dependencies\n", + " - [numpy: Scientific Computing Tools For Python](https://www.numpy.org) \n", + " - [scipy: Scientific Tools for Python](https://www.scipy.org/) \n", + " - [pyproj: Python interface to PROJ library](https://pypi.org/project/pyproj/) \n", + " - [netCDF4: Python interface to the netCDF C library](https://unidata.github.io/netcdf4-python/) \n", + " - [matplotlib: Python 2D plotting library](http://matplotlib.org/) \n", + " - [cartopy: Python package designed for geospatial data processing](https://scitools.org.uk/cartopy/docs/latest/) \n", + "\n", + "## Program Dependencies\n", + "\n", + "- `crs.py`: Coordinate Reference System (CRS) routines \n", + "- `io.model.py`: retrieves tide model parameters for named tide models \n", + "- `io.OTIS.py`: extract tidal harmonic constants from OTIS tide models \n", + "- `io.ATLAS.py`: extract tidal harmonic constants from ATLAS netcdf models \n", + "- `io.GOT.py`: extract tidal harmonic constants from GOT tide models \n", + "- `io.FES.py`: extract tidal harmonic constants from FES tide models \n", + "\n", + "This notebook uses Jupyter widgets to set parameters for calculating the tidal maps. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load modules" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib\n", + "matplotlib.rcParams['axes.linewidth'] = 2.0\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.colors as colors\n", + "import cartopy.crs as ccrs\n", + "\n", + "# import tide programs\n", + "import pyTMD.io\n", + "import pyTMD.tools\n", + "\n", + "# autoreload\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set parameters for program\n", + "\n", + "- Model directory \n", + "- Tide model " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# available model list\n", + "model_list = sorted(pyTMD.io.model.ocean_elevation())\n", + "# display widgets for setting directory and model\n", + "TMDwidgets = pyTMD.tools.widgets()\n", + "TMDwidgets.model.options = model_list\n", + "TMDwidgets.model.value = 'GOT4.10'\n", + "TMDwidgets.VBox([\n", + " TMDwidgets.directory,\n", + " TMDwidgets.model,\n", + " TMDwidgets.compress\n", + "])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup tide model parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# get model parameters\n", + "model = pyTMD.io.model(TMDwidgets.directory.value,\n", + " compressed=TMDwidgets.compress.value\n", + " ).elevation(TMDwidgets.model.value)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup coordinates for calculating tides" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create a global image\n", + "xlimits = [-180,180]\n", + "ylimits = [-90, 90]\n", + "spacing = [0.25, 0.25]\n", + "# x and y coordinates\n", + "x = np.arange(xlimits[0],xlimits[1]+spacing[0],spacing[0])\n", + "y = np.arange(ylimits[0],ylimits[1]+spacing[1],spacing[1])\n", + "xgrid,ygrid = np.meshgrid(x,y)\n", + "# x and y dimensions\n", + "nx = int((xlimits[1]-xlimits[0])/spacing[0])+1\n", + "ny = int((ylimits[1]-ylimits[0])/spacing[1])+1\n", + "# flatten latitude and longitude to arrays\n", + "lon,lat = xgrid.flatten(), ygrid.flatten()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate tidal form factors\n", + "\n", + "Calculate the ratios between major diurnal tides and major semi-diurnal tides\n", + "\n", + "- F: < 0.25: Semi-diurnal\n", + "- F: 0.25 - 1.5: Mixed predominantly semi-diurnal\n", + "- F: 1.5 - 3.0: Mixed predominantly diurnal\n", + "- F: > 3.0: Diurnal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read tidal constants and interpolate to grid points\n", + "if model.format in ('OTIS','ATLAS-compact','TMD3'):\n", + " amp,ph,D,c = pyTMD.io.OTIS.extract_constants(lon, lat, model.grid_file,\n", + " model.model_file, model.projection, type=model.type, crop=True,\n", + " method='spline', grid=model.file_format)\n", + "elif (model.format == 'ATLAS-netcdf'):\n", + " amp,ph,D,c = pyTMD.io.ATLAS.extract_constants(lon, lat, model.grid_file,\n", + " model.model_file, type=model.type, crop=True, method='spline',\n", + " scale=model.scale, compressed=model.compressed)\n", + "elif model.format in ('GOT-ascii', 'GOT-netcdf'):\n", + " amp,ph,c = pyTMD.io.GOT.extract_constants(lon, lat, model.model_file,\n", + " grid=model.file_format, crop=True, method='spline',\n", + " scale=model.scale, compressed=model.compressed)\n", + "elif (model.format == 'FES-netcdf'):\n", + " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,\n", + " type=model.type, version=model.version, crop=True,\n", + " method='spline', scale=model.scale, compressed=model.compressed)\n", + " c = model.constituents\n", + "\n", + "# find constituents for tidal form factors\n", + "k1 = c.index('k1')\n", + "o1 = c.index('o1')\n", + "m2 = c.index('m2')\n", + "s2 = c.index('s2')\n", + "# tidal form factor from Courtier\n", + "F = np.reshape((amp[:,k1] + amp[:,o1])/(amp[:,m2] + amp[:,s2]), (ny,nx))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create plot of tidal form factors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# cartopy transform for Equirectangular Projection\n", + "projection = ccrs.PlateCarree()\n", + "# create figure axis\n", + "fig, ax = plt.subplots(num=1, figsize=(5.5,3.5),\n", + " subplot_kw=dict(projection=projection))\n", + "# create boundary norm\n", + "boundary = [0.0, 0.25, 1.5, 3.0, 5.0]\n", + "ticklabels = ['Semi-Diurnal', 'Mixed SD', 'Mixed D', 'Diurnal']\n", + "norm = colors.BoundaryNorm(boundary, ncolors=256)\n", + "# plot tidal form factor\n", + "extent = (xlimits[0],xlimits[1],ylimits[0],ylimits[1])\n", + "im = ax.imshow(F, interpolation='nearest',\n", + " norm=norm, cmap='plasma', transform=projection,\n", + " extent=extent, origin='lower')\n", + "# add high resolution cartopy coastlines\n", + "ax.coastlines('10m')\n", + "\n", + "# Add colorbar and adjust size\n", + "# pad = distance from main plot axis\n", + "# extend = add extension triangles to upper and lower bounds\n", + "# options: neither, both, min, max\n", + "# shrink = percent size of colorbar\n", + "# aspect = lengthXwidth aspect of colorbar\n", + "cbar = plt.colorbar(im, ax=ax, extend='neither',\n", + " extendfrac=0.0375, orientation='horizontal', pad=0.025,\n", + " shrink=0.90, aspect=22, drawedges=False)\n", + "# rasterized colorbar to remove lines\n", + "cbar.solids.set_rasterized(True)\n", + "# Add label to the colorbar\n", + "cbar.ax.set_title('Tide Species Category', fontsize=13,\n", + " rotation=0, y=-2.0, va='top')\n", + "# Set the tick levels for the colorbar\n", + "cbar.set_ticks(ticks=[0.125, 0.875, 2.25, 4], labels=ticklabels)\n", + "\n", + "# axis = equal\n", + "ax.set_aspect('equal', adjustable='box')\n", + "# set x and y limits\n", + "ax.set_xlim(xlimits)\n", + "ax.set_ylim(ylimits)\n", + "\n", + "# no ticks on the x and y axes\n", + "ax.get_xaxis().set_ticks([])\n", + "ax.get_yaxis().set_ticks([])\n", + "# stronger linewidth on frame\n", + "ax.spines['geo'].set_linewidth(2.0)\n", + "ax.spines['geo'].set_capstyle('projecting')\n", + "\n", + "# adjust subplot within figure\n", + "fig.subplots_adjust(left=0.02,right=0.98,bottom=0.05,top=0.98)\n", + "# show the plot\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.14" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/doc/source/user_guide/Examples.rst b/doc/source/user_guide/Examples.rst index ea5d8601..75d00eae 100644 --- a/doc/source/user_guide/Examples.rst +++ b/doc/source/user_guide/Examples.rst @@ -21,6 +21,7 @@ The available examples include: ../notebooks/Plot-Ocean-Pole-Tide-Map ../notebooks/Plot-Ross-Ice-Shelf-Map ../notebooks/Plot-Tide-Forecasts + ../notebooks/Plot-Tide-Form-Factor ../notebooks/Solve-Synthetic-Tides .. grid:: 1 2 4 4 @@ -83,6 +84,11 @@ The available examples include: :img-top: ../_assets/tide_forecasts.png :link: ../notebooks/Plot-Tide-Forecasts.html + .. grid-item-card:: Plot Tide Form Factor + :text-align: center + :img-top: ../_assets/tide_form_factor.png + :link: ../notebooks/Plot-Tide-Form-Factor.html + .. grid-item-card:: Solve Synthetic Tides :text-align: center :img-top: ../_assets/solve_synthetic_tides.png From da01d659269528c600c61484baeb1649b42fbbca Mon Sep 17 00:00:00 2001 From: tsutterley Date: Thu, 7 Nov 2024 12:43:52 -0800 Subject: [PATCH 3/3] add Byun-Hart class --- .../notebooks/Plot-Tide-Form-Factor.ipynb | 89 +++++++++++++++---- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb b/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb index 8aadc759..4f784280 100644 --- a/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb +++ b/doc/source/notebooks/Plot-Tide-Form-Factor.ipynb @@ -8,7 +8,10 @@ "Plot Tide Form Factor\n", "======================\n", "\n", - "This ({nb-download}`notebook `) demonstrates plotting daily tidal form factors for determining the dominant species of a region using the classifications from [Courtier (1938)](https://journals.lib.unb.ca/index.php/ihr/article/download/27428/1882520184). The dominant species classifications do have limitations as pointed out by [Amin (1986)](https://journals.lib.unb.ca/index.php/ihr/article/download/23443/27218/0).\n", + "This ({nb-download}`notebook `) demonstrates plotting tidal form factors for classifying tides\n", + "\n", + "- Daily tidal form factors for determining the dominant species of a region using the classifications from [Courtier (1938)](https://journals.lib.unb.ca/index.php/ihr/article/download/27428/1882520184). The dominant species classifications do have limitations as pointed out by [Amin (1986)](https://journals.lib.unb.ca/index.php/ihr/article/download/23443/27218/0)\n", + "- Monthly tidal form factors for semi-diurnal species from [Byun and Hart](https://doi.org/10.5194/os-16-965-2020)\n", "\n", "OTIS format tidal solutions provided by Oregon State University and ESR \n", "- [http://volkov.oce.orst.edu/tides/region.html](http://volkov.oce.orst.edu/tides/region.html) \n", @@ -60,6 +63,7 @@ "import matplotlib.pyplot as plt\n", "import matplotlib.colors as colors\n", "import cartopy.crs as ccrs\n", + "import ipywidgets\n", "\n", "# import tide programs\n", "import pyTMD.io\n", @@ -150,14 +154,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Calculate tidal form factors\n", - "\n", - "Calculate the ratios between major diurnal tides and major semi-diurnal tides\n", - "\n", - "- F: < 0.25: Semi-diurnal\n", - "- F: 0.25 - 1.5: Mixed predominantly semi-diurnal\n", - "- F: 1.5 - 3.0: Mixed predominantly diurnal\n", - "- F: > 3.0: Diurnal" + "## Calculate tidal amplitudes and phases" ] }, { @@ -183,15 +180,75 @@ " amp,ph = pyTMD.io.FES.extract_constants(lon, lat, model.model_file,\n", " type=model.type, version=model.version, crop=True,\n", " method='spline', scale=model.scale, compressed=model.compressed)\n", - " c = model.constituents\n", + " c = model.constituents" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate tidal form factors\n", + "\n", + "Courtier form factor:\n", + "Ratios between major diurnal tides and major semi-diurnal tides\n", + "\n", + "- F: < 0.25: Semi-diurnal\n", + "- F: 0.25 - 1.5: Mixed predominantly semi-diurnal\n", + "- F: 1.5 - 3.0: Mixed predominantly diurnal\n", + "- F: > 3.0: Diurnal\n", + "\n", + "Byut-Hart form factor:\n", + "Ratios between semi-diurnal tides for monthly tidal envelopes\n", "\n", + "- E: < 0.8: Spring-Neap\n", + "- E: 0.8 - 1.0: Mixed predominantly Spring-Neap\n", + "- E: 1.0 - 1.15: Mixed predominantly Perigean-Apogean\n", + "- E: > 2.0: Perigean-Apogean\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "TMDwidgets.form_factor = ipywidgets.Dropdown(\n", + " options=['Courtier','Byun-Hart'],\n", + " value='Courtier',\n", + " description='Factor:',\n", + " disabled=False,\n", + " style=TMDwidgets.style,\n", + ")\n", + "display(TMDwidgets.form_factor)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "# find constituents for tidal form factors\n", "k1 = c.index('k1')\n", "o1 = c.index('o1')\n", "m2 = c.index('m2')\n", "s2 = c.index('s2')\n", - "# tidal form factor from Courtier\n", - "F = np.reshape((amp[:,k1] + amp[:,o1])/(amp[:,m2] + amp[:,s2]), (ny,nx))" + "n2 = c.index('n2')\n", + "# select form factor\n", + "if TMDwidgets.form_factor.value == 'Courtier':\n", + " # tidal form factor from Courtier\n", + " factor = np.reshape((amp[:,k1] + amp[:,o1])/(amp[:,m2] + amp[:,s2]), (ny,nx))\n", + " boundary = np.array([0.0, 0.25, 1.5, 3.0, 5.0])\n", + " ticklabels = ['Semi-Diurnal', 'Mixed SD', 'Mixed D', 'Diurnal']\n", + " longname = 'Tide Species Classification'\n", + "elif TMDwidgets.form_factor.value == 'Byun-Hart':\n", + " # semi-diurnal form factor from Byun and Hart\n", + " factor = np.reshape((amp[:,m2] + amp[:,n2])/(amp[:,m2] + amp[:,s2]), (ny,nx))\n", + " boundary = np.array([0.0, 0.8, 1.0, 1.15, 2.0])\n", + " ticklabels = ['Spring-Neap', 'Mixed S-N', 'Mixed P-A', 'Perigean-Apogean']\n", + " longname = 'Semi-Diurnal Classification'\n", + "# calculate ticks for labels\n", + "ticks = 0.5*(boundary[1:] + boundary[:-1])" ] }, { @@ -213,12 +270,10 @@ "fig, ax = plt.subplots(num=1, figsize=(5.5,3.5),\n", " subplot_kw=dict(projection=projection))\n", "# create boundary norm\n", - "boundary = [0.0, 0.25, 1.5, 3.0, 5.0]\n", - "ticklabels = ['Semi-Diurnal', 'Mixed SD', 'Mixed D', 'Diurnal']\n", "norm = colors.BoundaryNorm(boundary, ncolors=256)\n", "# plot tidal form factor\n", "extent = (xlimits[0],xlimits[1],ylimits[0],ylimits[1])\n", - "im = ax.imshow(F, interpolation='nearest',\n", + "im = ax.imshow(factor, interpolation='nearest',\n", " norm=norm, cmap='plasma', transform=projection,\n", " extent=extent, origin='lower')\n", "# add high resolution cartopy coastlines\n", @@ -236,10 +291,10 @@ "# rasterized colorbar to remove lines\n", "cbar.solids.set_rasterized(True)\n", "# Add label to the colorbar\n", - "cbar.ax.set_title('Tide Species Category', fontsize=13,\n", + "cbar.ax.set_title(longname, fontsize=13,\n", " rotation=0, y=-2.0, va='top')\n", "# Set the tick levels for the colorbar\n", - "cbar.set_ticks(ticks=[0.125, 0.875, 2.25, 4], labels=ticklabels)\n", + "cbar.set_ticks(ticks=ticks, labels=ticklabels)\n", "\n", "# axis = equal\n", "ax.set_aspect('equal', adjustable='box')\n",