Key focus of this article: Understand the relationship between analytic signal, Hilbert transform and FFT. Hands-on demonstration using Python and Matlab.
Introduction
Fourier Transform of a real-valued signal is complex-symmetric. It implies that the content at negative frequencies are redundant with respect to the positive frequencies. In their works, Gabor [1] and Ville [2], aimed to create an analytic signal by removing redundant negative frequency content resulting from the Fourier transform. The analytic signal is complex-valued but its spectrum will be one-sided (only positive frequencies) that preserved the spectral content of the original real-valued signal. Using an analytic signal instead of the original real-valued signal, has proven to be useful in many signal processing applications. For example, in spectral analysis, use of analytic signal in-lieu of the original real-valued signal mitigates estimation biases and eliminates cross-term artifacts due to negative and positive frequency components [3].
This article is part of the following books |
Continuous-time analytic signal
Let
Lets say the magnitude spectrum of
As mentioned in the introduction, an analytic signal can be formed by suppressing the negative frequency contents of the Fourier Transform of the real-valued signal. That is, in frequency domain, the spectral content
The corresponding spectrum of the resulting analytic signal is shown in Figure 1(b).
Since the spectrum of the analytic signal is one-sided, the analytic signal will be complex valued in the time domain, hence the analytic signal can be represented in terms of real and imaginary components as
It is interesting to note that Hilbert transform [4] can be used to find a companion function (imaginary part in the equation above) to a real-valued signal such that the real signal can be analytically extended from the real axis to the upper half of the complex plane . Denoting Hilbert transform as
From these discussion, we can see that an analytic signal
● Frequency domain approach: The one-sided spectrum of
● Time domain approach: Using Hilbert transform approach given in equation (4)
One of the important property of an analytic signal is that its real and imaginary components are orthogonal
Discrete-time analytic signal
Since we are in digital era, we are more interested in discrete-time signal processing. Consider a continuous real-valued signal
At this point, we would like to construct a discrete-time analytic signal
● The real part of the analytic signal should be same as the original real-valued signal.
● The real and imaginary part of the analytic signal should satisfy the following property of orthogonality
In Frequency domain approach for the continuous-time case, we saw that an analytic signal is constructed by suppressing the negative frequency components from the spectrum of the real signal. We cannot do this for our periodically sampled signal
Given a record of samples
● Compute the
● N-point periodic one-sided analytic signal is computed by the following transform
● Finally, the analytic signal (z[n]) is obtained by taking the inverse DTFT of
Matlab
The given procedure can be coded in Matlab using the FFT function. Given a record of
function z = analytic_signal(x) %x is a real-valued record of length N, where N is even %returns the analytic signal z[n] x = x(:); %serialize N = length(x); X = fft(x,N); z = ifft([X(1); 2*X(2:N/2); X(N/2+1); zeros(N/2-1,1)],N); end
To test this function, we create a 5 seconds record of a real-valued sine signal. The analytic signal is constructed and the orthogonal components are plotted in Figure 3. From the plot, we can see that the real part of the analytic signal is exactly same as the original signal (which is the cosine signal) and the imaginary part of the analytic signal is
t=0:0.001:0.5-0.001; x = sin(2*pi*10*t); %real-valued f = 10 Hz subplot(2,1,1); plot(t,x);%plot the original signal title('x[n] - original signal'); xlabel('n'); ylabel('x[n]'); z = analytic_signal(x); %construct analytic signal subplot(2,1,2); plot(t, real(z), 'k'); hold on; plot(t, imag(z), 'r'); title('Components of Analytic signal'); xlabel('n'); ylabel('z_r[n] and z_i[n]'); legend('Real(z[n])','Imag(z[n])');
Python
Equivalent code in Python is given below (tested with Python 3.6.0)
import numpy as np def main(): t = np.arange(start=0,stop=0.5,step=0.001) x = np.sin(2*np.pi*10*t) import matplotlib.pyplot as plt plt.subplot(2,1,1) plt.plot(t,x) plt.title('x[n] - original signal') plt.xlabel('n') plt.ylabel('x[n]') z = analytic_signal(x) plt.subplot(2,1,2) plt.plot(t,z.real,'k',label='Real(z[n])') plt.plot(t,z.imag,'r',label='Imag(z[n])') plt.title('Components of Analytic signal') plt.xlabel('n') plt.ylabel('z_r[n] and z_i[n]') plt.legend() def analytic_signal(x): from scipy.fftpack import fft,ifft N = len(x) X = fft(x,N) h = np.zeros(N) h[0] = 1 h[1:N//2] = 2*np.ones(N//2-1) h[N//2] = 1 Z = X*h z = ifft(Z,N) return z if __name__ == '__main__': main()
Hilbert Transform using FFT
We should note that the hilbert function in Matlab returns the analytic signal $latex z[n]$ not the hilbert transform of the signal
x_hilbert = imag(analytic_signal(x))
In the coming posts, we will some of the applications of constructing an analytic signal. For example: Find the instantaneous amplitude and phase of a signal, envelope detector for an amplitude modulated signal, detecting phase changes in a sine wave.
Rate this article: Note: There is a rating embedded within this post, please visit this post to rate it.
References:
[1] D. Gabor, “Theory of communications”, Journal of the Inst. Electr. Eng., vol. 93, pt. 111, pp. 42-57, 1946. See definition of complex signal on p. 432.↗
[2] J. A. Ville, “Theorie et application de la notion du signal analytique”, Cables el Transmission, vol. 2, pp. 61-74, 1948.↗
[3] S. M. Kay, “Maximum entropy spectral estimation using the analytical signal”, IEEE transactions on Acoustics, Speech, and Signal Processing, vol. 26, pp. 467-469, October 1978.↗
[4] Frank R. Kschischang, “The Hilbert Transform”, University of Toronto, October 22, 2006.↗
[5] S. L. Marple, “Computing the discrete-time ‘analytic’ signal via FFT,” Conference Record of the Thirty-First Asilomar Conference on Signals, Systems and Computers , Pacific Grove, CA, USA, 1997, pp. 1322-1325 vol.2.↗
Hi. Thank you so much for this interesting post. I just have a question about the python script.
It seems you made fft on a real value signal and got a complex vector as a result. Then at the end you reversed it by ifft. I expected to get again a real value vector, but surprisingly the output was complex too. I guess the zeros you added at the bottom of “h” caused it, but how? can you please explain a bit about how we got a complex vector at the output?
Thanks a million!
Please read and grasp the concept. The aim is not to demonstrate FFT/IFFT. The aim is to create an analytic signal (complex vector) from a real signal (real vector).
Many people writing CODE for signal processing use FFTs and HILBERT Transforms.
I have read descriptions of the HILBERT Transform. And I think that a little less math (and more words about how to operate on the complex numbers of the FFT bin locations , would be more useful. As an example, a HILBERT transform can be implemented by : taking the FFT of a timedomain signal, visit every bin of the FFT array, (set BIN 0] to ZERO. Then, visit each BIN , one at a time. swap the REALP value with the IMAGP (and then multiply the REALP by -1). Do this at each BIN. Then TAKE the INVERSE FFT of the modified frequency domain array to get the 90-degree phase shifted signal. Or take the FFT of a timedomain signal, (set BIN 0] to ZERO. Then, visit each BIN , one at a time, from BIN(N/2 +1) to BIN (N) and set the REALP to ZERO and the IMAGP to zero. Then TAKE the INVERSE FFT of the modified frequency domain array to get the 90-degree phase shifted signal. It is difficult to progress from integrals to what to do (in C or PYTHON) with the AMPLITUDE SAMPLES of a timedomain signal or what to do with the REALP and IMAGP of every complex number of the FFT BIN. It would be nice if the authors wrote the INTEGRALS and some pseudo-code. Thank you. Cesar in California
Hello, thank you for sharing this. I am having a problem with the instantaneous phase I am getting out of the hilbert(.) function in MATLAB, as well as when I do not use fft/ifft to get the analytical phase. So the general question is, does my phase get distorted when I use Hilbert Transform on a random signal?
More elaborate example on this is, when I generate a random signal of length T, and then keep this random signal fixed, then I generate, say, few more random signal of length S, and then concatenate it with my original signal of length T, I do see that there is slight phase distortion at the beginning of my signal. In other words, why concatenating some signal to the end of my original signal distorts the instantaneous phase, in particular, at the beginning?