Plot Tidal Spectra

This (notebook) demonstrates plotting the tidal spectra of potential amplitudes for semi-diurnal and diurnal constituents following Munk and Cartwright (1966), Cartwright and Tayler (1971) and Cartwright and Edden (1973)

Python Dependencies

Program Dependencies

  • astro.py: computes the basic astronomical mean longitudes

  • arguments.py: load the nodal corrections for tidal constituents

Load modules

from __future__ import print_function

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.offsetbox as offsetbox

# import tide programs
import pyTMD.astro
import pyTMD.arguments

# autoreload
%load_ext autoreload
%autoreload 2
def frequency(arguments):
    """
    Calculates the angular frequencies of constituents
    """
    # Modified Julian Dates at J2000
    MJD = np.array([51544.5, 51544.55])
    # time interval in seconds
    deltat = 86400.0*(MJD[1] - MJD[0])
    # calculate the mean longitudes of the sun and moon
    s, h, p, n, pp = pyTMD.astro.mean_longitudes(MJD, method='ASTRO5')
    # initial time conversions
    hour = 24.0*np.mod(MJD, 1)
    # convert from hours solar time into mean lunar time in degrees
    tau = 15.0*hour - s + h
    # determine equilibrium arguments
    fargs = np.c_[tau, s, h, p, n, pp]
    rates = (fargs[1,:] - fargs[0,:])/deltat
    fd = np.dot(rates, arguments)
    # convert to radians per second
    omega = 2.0*np.pi*fd/360.0
    return omega

Plot Cartwright-Tayler-Edden Tables

# Cartwright and Edden (1973) table with updated values
table = pyTMD.arguments._ce1973_table_1
# read the table
CTE = pyTMD.arguments._parse_tide_potential_table(table)
fig, ax = plt.subplots(ncols=2, sharey=True, figsize=(10, 5))
# major constituents to label
scons = ['2n2', 'm2', 's2', 'n2']
dcons = ['q1', 'o1', 'k1', 'j1']
# for each spectral line
for i, line in enumerate(CTE):
    # calculate the angular frequency
    arguments = np.array([line[c] for c in ['tau','s','h','p','n','pp']])
    omega = frequency(arguments)
    # convert to cycles per solar day
    f = omega*86400.0/(2.0*np.pi)
    # amplitude in cm
    amp = 100.0*np.abs(line['Hs3'])
    # get the constituent ID based on the first 6 arguments
    cons = pyTMD.arguments._to_constituent_id(arguments,
        arguments=6, raise_error=False)
    # plot amplitudes and color if in the major constituents list
    if cons in scons:
        ax[0].semilogy([f, f], [0.0, amp], 'r', zorder=1)
    elif cons in dcons:
        ax[1].semilogy([f, f], [0.0, amp], 'r', zorder=1)
    elif (f >= 1.75) and (f <= 2.10):
        ax[0].semilogy([f, f], [0.0, amp], '0.4', zorder=0)
    elif (f >= 0.80) and (f <= 1.15):
        ax[1].semilogy([f, f], [0.0, amp], '0.4', zorder=0)

# add labels for some major semi-diurnal constituents
for c in scons:
    omega = pyTMD.arguments.frequency(c)
    f = omega*86400.0/(2.0*np.pi)
    ax[0].text(f, 100.0, c, color='r', fontsize=10, ha='center')
# add labels for some major diurnal constituents
for c in dcons:
    omega = pyTMD.arguments.frequency(c)
    f = omega*86400.0/(2.0*np.pi)
    ax[1].text(f, 100.0, c, color='r', fontsize=10, ha='center')

# axes parameters
xlabels = ['Frequency [cpd]', 'Frequency [cpd]']
ylabels = ['Amplitude [cm]', '']
xlimits = [[1.75, 2.10], [0.80, 1.15]]
titles = ['Semi-diurnal', 'Diurnal']
labels = ['a)', 'b)']
# adjust axes
for i, axis in enumerate(ax):
    # add x and y labels
    axis.set_xlabel(xlabels[i])
    axis.set_ylabel(ylabels[i])
    # set limits
    axis.set_xlim(xlimits[i])
    axis.set_ylim(1e-3, 2e2)
    # set titles
    axis.set_title(f'{titles[i]} Tidal Spectra')
    # add labels
    at = offsetbox.AnchoredText(labels[i], loc=2, frameon=False,
        prop=dict(size=14,weight='bold'))
    axis.axes.add_artist(at)
    # adjust axes
    axis.get_xaxis().set_tick_params(which='both', direction='in')
    axis.get_yaxis().set_tick_params(which='both', direction='in')
# adjust subplots
fig.subplots_adjust(left=0.07, right=0.97, bottom=0.10, top=0.95, wspace=0.10)
plt.show()