2

I am trying to compute the envelope of a signal using the Hilbert transform in Scipy. Here is the code,

import numpy as np
from scipy.signal import hilbert
A=2
lamb=20
w=2*np.pi*100
signal = A**(-lamb*t)*(np.sin(w*t+5)+np.cos(w*t+5))
analytic_signal = hilbert(signal)
amplitude_envelope = np.abs(analytic_signal)

if one plots the signal and the envelope, the latter show quite high values both at the beginning and at the end... see figure attached. Any tips on how to fix this issue and get a better envelope?

Thanks in advance.enter image description here

uom0
  • 383
  • 2
  • 12

1 Answers1

2

A basic assumption of hilbert is that the input signal is periodic. If you extended your signal to be periodic, then at t=1 there would be a big jump from the long, flat tail to the repetition of the initial burst of the signal.

One way to handle this is to apply hilbert to an even extension of the signal, such as the concatenation of the signal with a reversed copy of itself, e.g. np.concatenate((signal[::-1], signal)). Here's a modified version of your script that does this:

import numpy as np
from scipy.signal import hilbert
import matplotlib.pyplot as plt


A = 2
lamb = 20
w = 2*np.pi*100

fs = 8000
T = 1.0
t = np.arange(int(fs*T)) / fs

signal = A**(-lamb*t)*(np.sin(w*t+5)+np.cos(w*t+5))

# Make an even extension of `signal`.
signal2 = np.concatenate((signal[::-1], signal))

analytic_signal2 = hilbert(signal2)

# Get the amplitude of the second half of analytic_signal2
amplitude_envelope = np.abs(analytic_signal2[len(t):])


plt.plot(t, signal, label='signal')
plt.plot(t, amplitude_envelope, label='envelope')
plt.xlabel('t')
plt.legend(framealpha=1, shadow=True)
plt.grid()
plt.show()

Here's the plot that is created by the script: enter image description here

Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
  • Thanks, Warren. Interesting. If, say fs=200, then the same problem arises even with this technique. I read somehwere this is a so-called Gibbs effect, but I ignore if this is the right argot. Do you have any clue of how to circumvent this in a more general manner? Thanks for your reply. – uom0 Jun 09 '20 at 09:14
  • 1
    The sample rate fs=200 is too low for the signal in your example. With fs=200, the result will exhibit [aliasing](https://en.wikipedia.org/wiki/Aliasing). The oscillatory part of the signal has frequency 100, and fs=200 is exactly the [Nyquist rate](https://en.wikipedia.org/wiki/Nyquist_rate) for a purely sinusoidal signal with frequency 100, but your signal is not a pure sinusoidal oscillation. It has exponential decay, so its spectral content will exceed 100. – Warren Weckesser Jun 09 '20 at 12:39
  • It makes sense. Thanks for your prompt response, Warren. Best. – uom0 Jun 09 '20 at 13:21