def _morsewave_first_family(fact, N, K, gamma, beta, w, psizero, norm): """See `help(_gmw.morsewave)`. See Olhede and Walden, "Noise reduction in directional signals using multiple Morse wavelets", IEEE Trans. Bio. Eng., v50, 51--57. The equation at the top right of page 56 is equivalent to the used expressions. Morse wavelets are defined in the frequency domain, and so not interpolated in the time domain in the same way as other continuous wavelets. """ r = (2 * beta + 1) / gamma c = r - 1 L = np.zeros(w.shape) psif = np.zeros((len(psizero), 1, K)) for k in range(K): # Log of gamma function much better ... trick from Maltab's ``beta'` if norm == 'energy': A = morseafun(gamma, beta, k + 1, norm='energy') coeff = np.sqrt(1. / fact) * A elif norm == 'bandpass': if beta == 0: coeff = 1. else: coeff = np.sqrt(np.exp(gammaln_fn(r) + gammaln_fn(k + 1) - gammaln_fn(k + r))) L[:N//2 + 1] = laguerre(2 * w[:N//2 + 1]**gamma, k, c).reshape(-1, 1) psif[:, :, k] = coeff * psizero * L return psif
def morseafun(gamma, beta, k=1, norm='bandpass'): """GMW amplitude or a-function (evaluated). Used internally by other funcs. # Arguments k: int >= 1 Order of the wavelet; see `help(_gmw.morsewave)`. gamma, beta: float, float Wavelet parameters. See `help(_gmw.morsewave)`. norm: str['energy', 'bandpass'] Wavelet normalization. See `help(_gmw.morsewave)`. # Returns A: float GMW amplitude (freq-domain peak value). ______________________________________________________________________ Lilly, J. M. (2021), jLab: A data analysis package for Matlab, v1.6.9, http://www.jmlilly.net/jmlsoft.html https://github.com/jonathanlilly/jLab/blob/master/jWavelet/morseafun.m """ if norm == 'energy': r = (2*beta + 1) / gamma A = np.sqrt(2*pi * gamma * (2**r) * np.exp(gammaln_fn(k) - gammaln_fn(k + r - 1))) elif norm == 'bandpass': if beta == 0: A = 2. else: wc = morsefreq(gamma, beta) A = 2. / np.exp(beta * np.log(wc) - wc**gamma) else: raise ValueError("unsupported `norm`: %s;" % norm + "must be one of: 'bandpass', 'energy'.") return A
def _gmw_k_constants(gamma, beta, k, norm='bandpass', dtype='float64'): """Laguerre polynomial constants & `coeff` term. Higher-order GMWs are coded such that constants are pre-computed and reused for any `w` input, since they remain fixed for said order. """ r = (2 * beta + 1) / gamma c = r - 1 # compute `coeff` if norm == 'bandpass': coeff = np.sqrt(np.exp(gammaln_fn(r) + gammaln_fn(k + 1) - gammaln_fn(k + r))) elif norm == 'energy': coeff = np.sqrt(2*pi * gamma * (2**r) * np.exp(gammaln_fn(k + 1) - gammaln_fn(k + r))) # compute Laguerre polynomial constants L_consts = np.zeros(k + 1, dtype=dtype) for m in range(k + 1): fact = np.exp(gammaln_fn(k + c + 1) - gammaln_fn(c + m + 1) - gammaln_fn(k - m + 1)) L_consts[m] = (-1)**m * fact / gamma_fn(m + 1) k_consts = L_consts * coeff if norm == 'bandpass': k_consts *= 2 k_consts = k_consts.astype(dtype) return k_consts
def laguerre(x, k, c): """Generalized Laguerre polynomials. See `help(_gmw.morsewave)`. LAGUERRE is used in the computation of the generalized Morse wavelets and uses the expression given by Olhede and Walden (2002), "Generalized Morse Wavelets", Section III D. """ x = np.atleast_1d(np.asarray(x).squeeze()) assert x.ndim == 1 y = np.zeros(x.shape) for m in range(k + 1): # Log of gamma function much better ... trick from Maltab's ``beta'' fact = np.exp(gammaln_fn(k + c + 1) - gammaln_fn(c + m + 1) - gammaln_fn(k - m + 1)) y += (-1)**m * fact * x**m / gamma_fn(m + 1) return y