Source code for utide.harmonics

"""
Function ut_E() returns complex exponential basis functions
for a given set of frequencies.
"""

import numpy as np

from ._ut_constants import ut_constants
from .astronomy import ut_astron

sat = ut_constants.sat
const = ut_constants.const
shallow = ut_constants.shallow

nshallow = np.ma.masked_invalid(const.nshallow)
ishallow = np.ma.masked_invalid(const.ishallow)
not_shallow = ishallow.mask  # True where it was masked.
nshallow = nshallow.compressed().astype(int)
ishallow = ishallow.compressed().astype(int) - 1
kshallow = np.nonzero(~not_shallow)[0]


def linearized_freqs(tref):
    astro, ader = ut_astron(tref)
    freq = const.freq.copy()
    selected = np.dot(const.doodson[not_shallow, :], ader) / 24
    freq[not_shallow] = selected.squeeze()
    for i0, nshal, k in zip(ishallow, nshallow, kshallow):
        ik = i0 + np.arange(nshal)
        freq[k] = (freq[shallow.iname[ik] - 1] * shallow.coef[ik]).sum()
    return freq


def ut_E(t, tref, frq, lind, lat, ngflgs, prefilt):
    """
    Compute complex exponential basis function.

    Parameters
    ----------
    t : array_like or float (nt,)
        time in days
    tref : float
        reference time in days
    frq : array_like or float (nc,)
        frequencies in cph
    lind : array_like or int (nc,)
        indices of constituents
    lat : float
        latitude, degrees N
    nflgs : array_like, bool
        [NodsatLint NodsatNone GwchLint GwchNone]
    prefilt: Bunch
        not implemented

    Returns
    -------
    E : array (nt, nc)
        complex exponential basis function; always returned as 2-D array
    """

    t = np.atleast_1d(t)
    frq = np.atleast_1d(frq)
    lind = np.atleast_1d(lind)
    nt = len(t)
    nc = len(frq)

    if ngflgs[1] and ngflgs[3]:
        F = np.ones((nt, nc))
        U = np.zeros((nt, nc))
        V = np.dot(24 * (t - tref)[:, None], frq[:, None].T)
    else:
        F, U, V = FUV(t, tref, lind, lat, ngflgs)

    E = F * np.exp(1j * (U + V) * 2 * np.pi)

    # if ~isempty(prefilt)
    # if len(prefilt)!=0:
    #     P=interp1(prefilt.frq,prefilt.P,frq).T
    #     P( P>max(prefilt.rng) | P<min(prefilt.rng) | isnan(P) )=1;
    #     E = E*P(ones(nt,1),:);

    return E


[docs] def FUV(t, tref, lind, lat, ngflgs): """ UT_FUV() compute nodal/satellite correction factors and astronomical argument inputs t = times [datenum UTC] (nt x 1) tref = reference time [datenum UTC] (1 x 1) lind = list indices of constituents in ut_constants.mat (nc x 1) lat = latitude [deg N] (1 x 1) ngflgs = [NodsatLint NodsatNone GwchLint GwchNone] each 0/1 output F = real nodsat correction to amplitude [unitless] (nt x nc) U = nodsat correction to phase [cycles] (nt x nc) V = astronomical argument [cycles] (nt x nc) UTide v1p0 9/2011 d.codiga@gso.uri.edu (uses parts of t_vuf.m from t_tide, Pawlowicz et al 2002) """ t = np.atleast_1d(t).flatten() nt = len(t) nc = len(lind) # nodsat if ngflgs[1]: F = np.ones((nt, nc)) U = np.zeros((nt, nc)) else: if ngflgs[0]: tt = np.array([tref]) else: tt = t ntt = len(tt) astro, ader = ut_astron(tt) if abs(lat) < 5: lat = np.sign(lat) * 5 slat = np.sin(np.deg2rad(lat)) rr = sat.amprat.copy() j = sat.ilatfac == 1 rr[j] *= 0.36309 * (1.0 - 5.0 * slat**2) / slat j = sat.ilatfac == 2 rr[j] *= 2.59808 * slat # sat.deldood is (162, 3); all other sat vars are (162,) uu = np.dot(sat.deldood, astro[3:6, :]) + sat.phcorr[:, None] np.fmod(uu, 1, out=uu) # fmod is matlab rem; differs from % op mat = rr[:, None] * np.exp(1j * 2 * np.pi * uu) nfreq = len(const.isat) # 162 F = np.ones((nfreq, ntt), dtype=complex) iconst = sat.iconst - 1 ind = np.unique(iconst) for ii in ind: F[ii, :] = 1 + np.sum(mat[iconst == ii], axis=0) U = np.angle(F) / (2 * np.pi) # cycles F = np.abs(F) for i0, nshal, k in zip(ishallow, nshallow, kshallow): ik = i0 + np.arange(nshal) j = shallow.iname[ik] - 1 exp1 = shallow.coef[ik, None] exp2 = np.abs(exp1) F[k, :] = np.prod(F[j, :] ** exp2, axis=0) U[k, :] = np.sum(U[j, :] * exp1, axis=0) F = F[lind, :].T U = U[lind, :].T # gwch (astron arg) if ngflgs[3]: # None (raw phase lags not Greenwich phase lags). freq = linearized_freqs(tref) V = 24 * (t[:, np.newaxis] - tref) * freq[lind] else: if ngflgs[2]: # Linearized times. tt = np.array([tref]) else: tt = t # Exact times. ntt = len(tt) astro, ader = ut_astron(tt) V = np.dot(const.doodson, astro) + const.semi[:, None] # V has nan values from both const.* arrays with np.errstate(invalid="ignore"): np.fmod(V, 1, out=V) for i0, nshal, k in zip(ishallow, nshallow, kshallow): ik = i0 + np.arange(nshal) j = shallow.iname[ik] - 1 exp1 = shallow.coef[ik, None] V[k, :] = np.sum(V[j, :] * exp1, axis=0) V = V[lind, :].T if ngflgs[2]: # linearized times freq = linearized_freqs(tref) V = V + 24 * (t[:, None] - tref) * freq[None, lind] return F, U, V