Spaces:
Running
Running
File size: 2,430 Bytes
936f6fa |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# -*- coding: utf-8 -*-
# Copyright 2014 João Felipe Santos, jfsantos@emt.inrs.ca
#
# This file is part of the SRMRpy library, and is licensed under the
# MIT license: https://github.com/jfsantos/SRMRpy/blob/master/LICENSE
import numpy as np
from numpy.fft import fft, ifft
# This is copied straight from scipy.signal. The reason is that scipy.signal's version
# will always use the fft and ifft functions from fftpack. If you have Anaconda with an MKL
# license, you can install the package mklfft, which will plug the faster MKL FFT functions
# into numpy.
def hilbert(x, N=None, axis=-1):
"""
Compute the analytic signal, using the Hilbert transform.
The transformation is done along the last axis by default.
Parameters
----------
x : array_like
Signal data. Must be real.
N : int, optional
Number of Fourier components. Default: ``x.shape[axis]``
axis : int, optional
Axis along which to do the transformation. Default: -1.
Returns
-------
xa : ndarray
Analytic signal of `x`, of each 1-D array along `axis`
Notes
-----
The analytic signal ``x_a(t)`` of signal ``x(t)`` is:
.. math:: x_a = F^{-1}(F(x) 2U) = x + i y
where `F` is the Fourier transform, `U` the unit step function,
and `y` the Hilbert transform of `x`. [1]_
In other words, the negative half of the frequency spectrum is zeroed
out, turning the real-valued signal into a complex signal. The Hilbert
transformed signal can be obtained from ``np.imag(hilbert(x))``, and the
original signal from ``np.real(hilbert(x))``.
References
----------
.. [1] Wikipedia, "Analytic signal".
http://en.wikipedia.org/wiki/Analytic_signal
"""
x = np.asarray(x)
if np.iscomplexobj(x):
raise ValueError("x must be real.")
if N is None:
N = x.shape[axis]
# Make N multiple of 16 to make sure the transform will be fast
if N % 16:
N = int(np.ceil(N/16)*16)
if N <= 0:
raise ValueError("N must be positive.")
Xf = fft(x, N, axis=axis)
h = np.zeros(N)
if N % 2 == 0:
h[0] = h[N // 2] = 1
h[1:N // 2] = 2
else:
h[0] = 1
h[1:(N + 1) // 2] = 2
if len(x.shape) > 1:
ind = [np.newaxis] * x.ndim
ind[axis] = slice(None)
h = h[ind]
y = ifft(Xf * h, axis=axis)
return y[:x.shape[axis]]
|